Index: lld/ELF/InputFiles.cpp =================================================================== --- lld/ELF/InputFiles.cpp +++ lld/ELF/InputFiles.cpp @@ -205,14 +205,31 @@ uint64_t Offset) { llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); }); + // detect SectionIndex for specified section. + // TODO : put section index information into InputSectionBase itself + // to not loop over all sections. + 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) { + llvm::SectionedAddress Address; + Address.Address = S->getOffsetInFile() + Offset; + Address.SectionIndex = SectionIndex; + if (LT->getFileLineInfoForAddress( - S->getOffsetInFile() + Offset, nullptr, + Address, 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 @@ -319,11 +319,14 @@ /// given address where applicable. 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(); } 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,18 @@ static void dumpTableHeader(raw_ostream &OS); static bool orderByAddress(const Row &LHS, const Row &RHS) { - return LHS.Address < RHS.Address; + return (LHS.SectionIndex < RHS.SectionIndex) || + (LHS.SectionIndex == RHS.SectionIndex && + LHS.Address < RHS.Address); } /// The program-counter value corresponding to a machine instruction /// generated by the compiler. uint64_t Address; + /// If relocation information presented then this is the Index of section + /// which contains above address. Otherwise this is + /// object::SectionedAddress::Undef value. + uint64_t SectionIndex; /// 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 +198,10 @@ /// and is described by line table rows [FirstRowIndex, LastRowIndex). uint64_t LowPC; uint64_t HighPC; + /// If relocation information presented then this is the Index of section + /// which contains above addresses. Otherwise this is + /// object::SectionedAddress::Undef value. + uint64_t SectionIndex; unsigned FirstRowIndex; unsigned LastRowIndex; bool Empty; @@ -199,14 +209,18 @@ void reset(); static bool orderByLowPC(const Sequence &LHS, const Sequence &RHS) { - return LHS.LowPC < RHS.LowPC; + return (LHS.SectionIndex < RHS.SectionIndex) || + (LHS.SectionIndex == RHS.SectionIndex && LHS.LowPC < RHS.LowPC); } bool isValid() const { return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); } - bool containsPC(uint64_t PC) const { return (LowPC <= PC && PC < HighPC); } + bool containsPC(SectionedAddress PC) const { + return SectionIndex == PC.SectionIndex && + (LowPC <= PC.Address && PC.Address < HighPC); + } }; struct LineTable { @@ -223,9 +237,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(llvm::SectionedAddress Address) const; - bool lookupAddressRange(uint64_t Address, uint64_t Size, + bool lookupAddressRange(llvm::SectionedAddress Address, uint64_t Size, std::vector &Result) const; bool hasFileAtIndex(uint64_t FileIndex) const; @@ -238,7 +252,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(llvm::SectionedAddress Address, + const char *CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, DILineInfo &Result) const; @@ -263,10 +278,15 @@ private: uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq, - uint64_t Address) const; + SectionedAddress Address) const; Optional getSourceByIndex(uint64_t FileIndex, DILineInfoSpecifier::FileLineInfoKind Kind) const; + + uint32_t lookupAddressMain(SectionedAddress Address) const; + + bool lookupAddressRangeMain(SectionedAddress Address, uint64_t Size, + std::vector &Result) const; }; const LineTable *getLineTable(uint32_t Offset) const; 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 @@ -57,13 +57,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,25 @@ const ObjectFile *getObject() const; }; +struct SectionedAddress { + SectionedAddress() : SectionIndex(UndefSection), Address(0) {} + SectionedAddress(uint64_t SI, uint64_t VMA) + : SectionIndex(SI), Address(VMA) {} + SectionedAddress(const SectionedAddress &Other) + : SectionIndex(Other.SectionIndex), Address(Other.Address) {} + + bool operator<(const SectionedAddress &Other) const { + return (this->SectionIndex < Other.SectionIndex) || + (this->SectionIndex == Other.SectionIndex && + this->Address < Other.Address); + } + + const static uint64_t UndefSection = UINT64_MAX; + + uint64_t SectionIndex; + uint64_t 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 { @@ -302,7 +321,7 @@ virtual void setARMSubArch(Triple &TheTriple) const { } virtual Expected getStartAddress() const { return errorCodeToError(object_error::parse_failed); - }; + } /// Create a triple from the data in this object file. Triple makeTriple() const; 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; @@ -966,36 +966,39 @@ 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(), + if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) { + llvm::SectionedAddress Addr; + Addr.Address = Address.Address; + Addr.SectionIndex = Address.SectionIndex; + LineTable->getFileLineInfoForAddress(Addr, 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,12 @@ // Get the index of row we're looking for in the line table. std::vector RowVector; - if (!LineTable->lookupAddressRange(Address, Size, RowVector)) + SectionedAddress Addr; + Addr.Address = Address.Address; + Addr.SectionIndex = Address.SectionIndex; + if (!LineTable->lookupAddressRange(Addr, Size, RowVector)) { return Lines; + } for (uint32_t RowIndex : RowVector) { // Take file number and line/column from the row. @@ -1031,26 +1038,28 @@ } 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)) + llvm::SectionedAddress Addr; + Addr.Address = Address.Address; + Addr.SectionIndex = Address.SectionIndex; + if (LineTable && LineTable->getFileLineInfoForAddress( + Addr, CU->getCompilationDir(), Spec.FLIKind, Frame)) InliningInfo.addFrame(Frame); } return InliningInfo; @@ -1070,9 +1079,13 @@ // For the topmost frame, initialize the line table of this // compile unit and fetch file/line info from it. LineTable = getLineTableForUnit(CU); + llvm::SectionedAddress Addr; + Addr.Address = Address.Address; + Addr.SectionIndex = Address.SectionIndex; + // For the topmost routine, get file/line info from line table. if (LineTable) - LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), + LineTable->getFileLineInfoForAddress(Addr, CU->getCompilationDir(), Spec.FLIKind, Frame); } else { // Otherwise, use call file, call line and call column from 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 @@ -354,6 +354,7 @@ void DWARFDebugLine::Row::reset(bool DefaultIsStmt) { Address = 0; + SectionIndex = object::SectionedAddress::UndefSection; Line = 1; Column = 0; File = 1; @@ -386,6 +387,7 @@ void DWARFDebugLine::Sequence::reset() { LowPC = 0; HighPC = 0; + SectionIndex = object::SectionedAddress::UndefSection; FirstRowIndex = 0; LastRowIndex = 0; Empty = true; @@ -435,6 +437,7 @@ // Record the end of instruction sequence. Sequence.HighPC = Row.Address; Sequence.LastRowIndex = RowNumber; + Sequence.SectionIndex = Row.SectionIndex; if (Sequence.isValid()) LineTable->appendSequence(Sequence); Sequence.reset(); @@ -565,7 +568,8 @@ ExtOffset, DebugLineData.getAddressSize(), Len - 1); } - State.Row.Address = DebugLineData.getRelocatedAddress(OffsetPtr); + State.Row.Address = DebugLineData.getRelocatedAddress( + OffsetPtr, &State.Row.SectionIndex); if (OS) *OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address); break; @@ -852,14 +856,16 @@ uint32_t DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &Seq, - uint64_t Address) const { + 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. DWARFDebugLine::Row Row; - Row.Address = Address; + Row.Address = Address.Address; + Row.SectionIndex = Address.SectionIndex; RowIter FirstRow = Rows.begin() + Seq.FirstRowIndex; RowIter LastRow = Rows.begin() + Seq.LastRowIndex; LineTable::RowIter RowPos = std::lower_bound( @@ -867,8 +873,9 @@ if (RowPos == LastRow) { return Seq.LastRowIndex - 1; } + assert(Seq.SectionIndex == RowPos->SectionIndex); uint32_t Index = Seq.FirstRowIndex + (RowPos - FirstRow); - if (RowPos->Address > Address) { + if (RowPos->Address > Address.Address) { if (RowPos == FirstRow) return UnknownRowIndex; else @@ -877,42 +884,87 @@ return Index; } -uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t Address) const { +uint32_t +DWARFDebugLine::LineTable::lookupAddress(SectionedAddress Address) const { + + // Search for relocatable addresses + uint32_t Result = lookupAddressMain(Address); + + if (Result == UnknownRowIndex) { + if (Address.SectionIndex != object::SectionedAddress::UndefSection) { + // Search for absolute addresses + Address.SectionIndex = object::SectionedAddress::UndefSection; + + Result = lookupAddressMain(Address); + } + } + + return Result; +} + +uint32_t +DWARFDebugLine::LineTable::lookupAddressMain(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 { + SectionedAddress Address, uint64_t Size, + std::vector &Result) const { + + // Search for relocatable addresses + bool AddressFound = lookupAddressRangeMain(Address, Size, Result); + + if (!AddressFound) { + if (Address.SectionIndex != object::SectionedAddress::UndefSection) { + // Search for absolute addresses + Address.SectionIndex = object::SectionedAddress::UndefSection; + + AddressFound = lookupAddressRangeMain(Address, Size, Result); + } + } + + return AddressFound; +} + +bool DWARFDebugLine::LineTable::lookupAddressRangeMain( + 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) { if (SeqPos == FirstSeq) return false; SeqPos--; @@ -934,7 +986,9 @@ FirstRowIndex = findRowInSeq(CurSeq, Address); // Figure out the last row in the range. - uint32_t LastRowIndex = findRowInSeq(CurSeq, EndAddr - 1); + SectionedAddress LastAddress = Address; + LastAddress.Address = EndAddr - 1; + uint32_t LastRowIndex = findRowInSeq(CurSeq, LastAddress); if (LastRowIndex == UnknownRowIndex) LastRowIndex = CurSeq.LastRowIndex - 1; @@ -1011,12 +1065,13 @@ } bool DWARFDebugLine::LineTable::getFileLineInfoForAddress( - uint64_t Address, const char *CompDir, FileLineInfoKind Kind, + 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) + if (RowIndex == UnknownRowIndex) { return false; + } // Take file number and line/column from the row. const auto &Row = Rows[RowIndex]; if (!getFileNameByIndex(Row.File, CompDir, Kind, Result.FileName)) 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, 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/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,29 @@ } 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( + object::SectionedAddress(Address.SectionIndex, + LineInfo->getVirtualAddress()), + 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 @@ -217,9 +217,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( @@ -229,7 +230,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; } @@ -238,7 +239,8 @@ } DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode( - uint64_t ModuleOffset, FunctionNameKind FNKind, bool UseSymbolTable) const { + object::SectionedAddress ModuleOffset, FunctionNameKind FNKind, + bool UseSymbolTable) const { DIInliningInfo InlinedContext; if (DebugInfoContext) @@ -252,7 +254,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; @@ -262,9 +264,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/Inputs/function-sections-line-numbers.cpp =================================================================== --- /dev/null +++ llvm/test/tools/llvm-objdump/Inputs/function-sections-line-numbers.cpp @@ -0,0 +1,25 @@ + +__attribute__((__noinline__)) + int Pow(int number, int count); + + + + + + +int Pow(int number, int count) { + int result = 1; + + for (int i = 0; i < count; ++i) { + result = result * number; + } + + return result; +} + + +extern "C" int Func (void) +{ + return Pow(6, 0); +} + Index: llvm/test/tools/llvm-objdump/function-sections-line-numbers.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-objdump/function-sections-line-numbers.test @@ -0,0 +1,10 @@ +# RUN: clang -ffunction-sections -gdwarf-5 -O -c %p/Inputs/function-sections-line-numbers.cpp -o %t.o +# RUN: llvm-objdump -disassemble -line-numbers -r -s -section-headers -t %t.o | FileCheck %s + + +# CHECK: 0000000000000000 _Z3Powii +# CHECK-NOT: function-sections-line-numbers.cpp:2 +# CHECK: function-sections-line-numbers.cpp:1 +# CHECK-NOT: function-sections-line-numbers.cpp:2 +# CHECK: 0000000000000000 Func +# CHECK: function-sections-line-numbers.cpp:2 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); + uint64_t SectionIndex, uint64_t SectionAddress); // 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,12 +460,14 @@ ArrayRef SectionBytes((const uint8_t *)SectionContents.data(), Section.getSize()); - parseSectionContents(SectionBytes, Section.getAddress()); + parseSectionContents(SectionBytes, Section.getIndex(), + Section.getAddress()); } return Error::success(); } void FileAnalysis::parseSectionContents(ArrayRef SectionBytes, + uint64_t SectionIndex, uint64_t SectionAddress) { assert(Symbolizer && "Symbolizer is uninitialised."); MCInst Instruction; @@ -509,8 +514,11 @@ // Check if this instruction exists in the range of the DWARF metadata. if (!IgnoreDWARFFlag) { + object::SectionedAddress ModuleAddress; + ModuleAddress.Address = VMAddress; + ModuleAddress.SectionIndex = SectionIndex; auto LineInfo = - Symbolizer->symbolizeCode(Object->getFileName(), VMAddress); + Symbolizer->symbolizeCode(Object->getFileName(), ModuleAddress); if (!LineInfo) { handleAllErrors(LineInfo.takeError(), [](const ErrorInfoBase &E) { errs() << "Symbolizer failed to get line: " << E.message() << "\n"; @@ -522,7 +530,12 @@ continue; } - IndirectInstructions.insert(VMAddress); + object::SectionedAddress Address; + + Address.Address = VMAddress; + Address.SectionIndex = SectionIndex; + + IndirectInstructions.insert(Address); } } 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); + uint64_t SectionIndex, uint64_t 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,6 +93,7 @@ } GraphResult GraphBuilder::buildFlowGraph(const FileAnalysis &Analysis, + uint64_t SectionIndex, uint64_t Address) { GraphResult Result; Result.BaseAddress = Address; @@ -100,8 +101,14 @@ const auto &IndirectInstructions = Analysis.getIndirectInstructions(); - if (IndirectInstructions.find(Address) == IndirectInstructions.end()) + // check that IndirectInstructions contains specified Address + object::SectionedAddress CheckedAddress; + CheckedAddress.Address = Address; + CheckedAddress.SectionIndex = SectionIndex; + + if (IndirectInstructions.find(CheckedAddress) == IndirectInstructions.end()) { return Result; + } buildFlowGraphImpl(Analysis, OpenedNodes, Result, 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,9 +130,10 @@ std::map BlameCounter; - for (uint64_t Address : Analysis.getIndirectInstructions()) { - const auto &InstrMeta = Analysis.getInstructionOrDie(Address); - GraphResult Graph = GraphBuilder::buildFlowGraph(Analysis, Address); + for (object::SectionedAddress Address : Analysis.getIndirectInstructions()) { + const auto &InstrMeta = Analysis.getInstructionOrDie(Address.Address); + GraphResult Graph = GraphBuilder::buildFlowGraph( + Analysis, Address.SectionIndex, Address.Address); CFIProtectionStatus ProtectionStatus = Analysis.validateCFIProtection(Graph); @@ -153,7 +154,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 +165,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 @@ -377,9 +377,30 @@ Die.dump(OS, 0, getDumpOpts()); } +// 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(ObjectFile &Obj, + uint64_t Address) { + + for (SectionRef Sec : Obj.sections()) { + if (!Sec.isText() || Sec.isVirtual()) + continue; + + if (Address >= Sec.getAddress() && + Address <= Sec.getAddress() + Sec.getSize()) { + return Sec.getIndex(); + } + } + + return object::SectionedAddress::UndefSection; +} + /// 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) { +static bool lookup(ObjectFile &Obj, DWARFContext &DICtx, uint64_t Address, + raw_ostream &OS) { auto DIEsForAddr = DICtx.getDIEsForAddress(Lookup); if (!DIEsForAddr) @@ -394,7 +415,11 @@ DIEsForAddr.BlockDIE.dump(OS, 4, DumpOpts); } - if (DILineInfo LineInfo = DICtx.getLineInfoForAddress(Lookup)) + object::SectionedAddress ModuleAddress; + ModuleAddress.Address = Lookup; + ModuleAddress.SectionIndex = + getModuleSectionIndexForAddress(Obj, ModuleAddress.Address); + if (DILineInfo LineInfo = DICtx.getLineInfoForAddress(ModuleAddress)) LineInfo.dump(OS); return true; @@ -413,7 +438,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,8 @@ // Print debug info. if (diContext) { - DILineInfo dli = diContext->getLineInfoForAddress(PC); + DILineInfo dli = diContext->getLineInfoForAddress( + object::SectionedAddress(SectIdx, PC)); // 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 @@ -491,7 +491,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 = "; "); }; @@ -521,7 +522,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; @@ -582,14 +584,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); @@ -616,13 +619,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; } @@ -644,9 +647,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; @@ -658,7 +661,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; @@ -676,7 +679,7 @@ OS << " } " << PacketBundle.second; PrintReloc(); Bytes = Bytes.slice(4); - Address += 4; + Address.Address += 4; } } }; @@ -685,8 +688,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); @@ -716,7 +719,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))) @@ -737,13 +740,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); @@ -1302,7 +1305,9 @@ PIP.printInst( *IP, Disassembled ? &Inst : nullptr, Bytes.slice(Index, Size), - SectionAddr + Index + VMAAdjustment, outs(), "", *STI, &SP, &Rels); + object::SectionedAddress(Section.getIndex(), + SectionAddr + Index + VMAAdjustment), + 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,24 @@ 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 { + auto SecOrErr = Sym.getSection(); + if (SecOrErr) { + 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 @@ -190,23 +190,56 @@ 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.get().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; + ModuleOffset.Address = Offset; + ModuleOffset.SectionIndex = + getModuleSectionIndexForAddress(ModuleName, ModuleOffset.Address); 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,11 @@ return F.str(); } - if (auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, It->second)) { + object::SectionedAddress ModuleAddress; + ModuleAddress.Address = It->second; + // TODO: set proper section index here + 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 +55,11 @@ 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 + 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 @@ -610,6 +610,82 @@ std::unique_ptr UserBlacklist; }; +// This is helper class: allows to detect SectionIndex by 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). +class SectionsIndexCache { +public: + SectionsIndexCache(const std::string &ObjectFile) { + Expected> BinaryOrErr = + object::createBinary(ObjectFile); + + failIfError(BinaryOrErr); + + object::Binary &Binary = *BinaryOrErr.get().getBinary(); + + if (object::ObjectFile *O = dyn_cast(&Binary)) { + for (object::SectionRef Sec : (*O).sections()) { + if (!Sec.isText() || Sec.isVirtual()) + continue; + + SectionInfo Section; + + Section.Address = Sec.getAddress(); + Section.Size = Sec.getSize(); + Section.Index = Sec.getIndex(); + + Sections.push_back(Section); + } + } + + llvm::sort(Sections.begin(), Sections.end(), OrderByAddress); + } + + uint64_t GetSectionIndexForAddress(uint64_t Address) { + + SectionInfo Sec; + Sec.Address = Address; + Sec.Size = 0; + + std::vector::const_iterator FoundSec = + std::lower_bound(Sections.begin(), Sections.end(), Sec, OrderByAddress); + + if (FoundSec == Sections.end()) { + return object::SectionedAddress::UndefSection; + } else if (Address >= FoundSec->Address && + Address <= (FoundSec->Address + FoundSec->Size)) { + return FoundSec->Index; + } else { + if (FoundSec == Sections.begin()) { + return object::SectionedAddress::UndefSection; + } + + FoundSec--; + + if (Address >= FoundSec->Address && + Address <= (FoundSec->Address + FoundSec->Size)) { + return FoundSec->Index; + }; + } + + return object::SectionedAddress::UndefSection; + } + +protected: + struct SectionInfo { + uint64_t Address; + uint64_t Size; + uint64_t Index; + }; + + static bool OrderByAddress(const SectionInfo &LHS, const SectionInfo &RHS) { + return LHS.Address < RHS.Address; + } + + std::vector Sections; +}; + static std::vector getCoveragePoints(const std::string &ObjectFile, const std::set &Addrs, @@ -618,13 +694,20 @@ auto Symbolizer(createSymbolizer()); Blacklists B; + SectionsIndexCache Sections(ObjectFile); + std::set CoveredFiles; if (ClSkipDeadFiles) { for (auto Addr : CoveredAddrs) { - auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, Addr); + object::SectionedAddress ModuleAddress; + ModuleAddress.Address = Addr; + ModuleAddress.SectionIndex = Sections.GetSectionIndexForAddress(Addr); + + 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 +719,11 @@ for (auto Addr : Addrs) { std::set Infos; // deduplicate debug info. - auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, Addr); + object::SectionedAddress ModuleAddress; + ModuleAddress.Address = Addr; + ModuleAddress.SectionIndex = Sections.GetSectionIndexForAddress(Addr); + + auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, ModuleAddress); failIfError(LineInfo); if (ClSkipDeadFiles && CoveredFiles.find(LineInfo->FileName) == CoveredFiles.end()) @@ -650,7 +737,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); @@ -953,11 +1041,17 @@ Hasher.update((*BufOrErr)->getBuffer()); Coverage->BinaryHash = toHex(Hasher.final()); + SectionsIndexCache Sections(ObjectFile); + Blacklists B; auto Symbolizer(createSymbolizer()); for (uint64_t Addr : *Data.Addrs) { - auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, Addr); + object::SectionedAddress ModuleAddress; + ModuleAddress.Address = Addr; + ModuleAddress.SectionIndex = Sections.GetSectionIndexForAddress(Addr); + + auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, ModuleAddress); failIfError(LineInfo); if (B.isBlacklisted(*LineInfo)) continue; Index: llvm/tools/sanstats/sanstats.cpp =================================================================== --- llvm/tools/sanstats/sanstats.cpp +++ llvm/tools/sanstats/sanstats.cpp @@ -81,11 +81,15 @@ if (Begin == End) return nullptr; + object::SectionedAddress ModuleAddress; + ModuleAddress.Address = Addr - 1; + ModuleAddress.SectionIndex = object::SectionedAddress::UndefSection; + // 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)) { + Symbolizer.symbolizeCode(Filename, ModuleAddress)) { 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,9 @@ // Expose this method publicly for testing. void parseSectionContents(ArrayRef SectionBytes, - uint64_t SectionAddress) { - FileAnalysis::parseSectionContents(SectionBytes, SectionAddress); + uint64_t SectionIndex, uint64_t SectionAddress) { + FileAnalysis::parseSectionContents(SectionBytes, SectionIndex, + SectionAddress); } Error initialiseDisassemblyMembers() { @@ -106,7 +107,7 @@ 0x41, 0x0e, // 21: rex.B (bad) 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1} }, - 0xDEADBEEF); + 0x0, 0xDEADBEEF); EXPECT_EQ(nullptr, Analysis.getInstruction(0x0)); EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000)); @@ -210,7 +211,7 @@ 0x2f, // 1: (bad) 0x90 // 2: nop }, - 0xDEADBEEF); + 0x0, 0xDEADBEEF); const auto &BadInstrMeta = Analysis.getInstructionOrDie(0xDEADBEEF + 1); const auto *GoodInstrMeta = Analysis.getPrevInstructionSequential(BadInstrMeta); @@ -240,7 +241,7 @@ 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1} 0x0f, 0x0b // 28: ud2 }, - 0xDEADBEEF); + 0x0, 0xDEADBEEF); EXPECT_FALSE(Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF))); EXPECT_FALSE( @@ -275,7 +276,7 @@ 0x75, 0x00, // 17: jne +0 0xc3, // 19: retq }, - 0xDEADBEEF); + 0x0, 0xDEADBEEF); EXPECT_TRUE( Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF))); @@ -322,7 +323,7 @@ 0xeb, 0xdd, // 36: jmp 3 [-35] 0xeb, 0xdc, // 38: jmp 4 [-36] }, - 0xDEADBEEF); + 0x0, 0xDEADBEEF); const auto *Current = Analysis.getInstruction(0xDEADBEEF); const auto *Next = Analysis.getDefiniteNextInstruction(*Current); @@ -412,7 +413,7 @@ 0xeb, 0xdd, // 36: jmp 3 [-35] 0xeb, 0xdc, // 38: jmp 4 [-36] }, - 0xDEADBEEF); + 0x0, 0xDEADBEEF); const auto *InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF); std::set XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); @@ -503,17 +504,17 @@ 0x0f, 0x0b, // 1: ud2 0x75, 0x00, // 3: jne 5 [+0] }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF); + 0x0, 0xDEADBEEF); + GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF); EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF, Analysis.validateCFIProtection(Result)); - Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 1); + Result = GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 1); EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF, Analysis.validateCFIProtection(Result)); - Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); + Result = GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 3); EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF, Analysis.validateCFIProtection(Result)); - Result = GraphBuilder::buildFlowGraph(Analysis, 0x12345678); + Result = GraphBuilder::buildFlowGraph(Analysis, 0x0, 0x12345678); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 4); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 2); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 3); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 3); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -596,12 +601,13 @@ 0xff, 0x10, // 6: callq *(%rax) 0x0f, 0x0b, // 8: ud2 }, - 0xDEADBEEF); + 0x0, 0xDEADBEEF); uint64_t PrevSearchLengthForConditionalBranch = SearchLengthForConditionalBranch; SearchLengthForConditionalBranch = 2; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 6); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 6); EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, Analysis.validateCFIProtection(Result)); @@ -621,11 +627,12 @@ 0x90, // 7: nop 0x0f, 0x0b, // 8: ud2 }, - 0xDEADBEEF); + 0x0, 0xDEADBEEF); uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; SearchLengthForUndef = 2; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 2); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 4); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 4); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -685,10 +694,11 @@ 0x90, // 21: nop 0x0f, 0x0b, // 22: ud2 }, - 0xDEADBEEF); + 0x0, 0xDEADBEEF); uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; SearchLengthForUndef = 5; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 9); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 9); 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); + 0x0, 0x688118); uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; SearchLengthForUndef = 1; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x68811d); + GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x0, 0x68811d); 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); + 0x0, 0x7759eb); Analysis.parseSectionContents( { @@ -729,24 +739,24 @@ 0x48, 0x89, 0xde, // 0x775a65: mov %rbx,%rsi 0xff, 0xd1, // 0x775a68: callq *%rcx }, - 0x775a56); + 0x0, 0x775a56); Analysis.parseSectionContents( { 0x0f, 0x0b, // 0x775e0e: ud2 }, - 0x775e0e); + 0x0, 0x775e0e); uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; SearchLengthForUndef = 1; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x775a68); + GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x0, 0x775a68); EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH, Analysis.validateCFIProtection(Result)); SearchLengthForUndef = 2; - Result = GraphBuilder::buildFlowGraph(Analysis, 0x775a68); + Result = GraphBuilder::buildFlowGraph(Analysis, 0x0, 0x775a68); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); SearchLengthForUndef = 3; - Result = GraphBuilder::buildFlowGraph(Analysis, 0x775a68); + Result = GraphBuilder::buildFlowGraph(Analysis, 0x0, 0x775a68); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 10); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 8); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 9); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 4); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -825,8 +839,8 @@ { 0x00, 0x01, 0x3f, 0xd6, // 0: blr x8 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF); + 0x0, 0xDEADBEEF); + GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF); EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, Analysis.validateCFIProtection(Result)); } @@ -840,8 +854,9 @@ 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1 0x00, 0x01, 0x3f, 0xd6, // 8: blr x8 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 8); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 8); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -856,8 +871,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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 12); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -872,8 +888,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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 12); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -889,8 +906,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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 16); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -906,8 +924,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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 16); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -923,8 +942,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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 16); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -940,8 +960,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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 16); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -957,8 +978,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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 16); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -974,8 +996,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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 16); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -990,8 +1013,9 @@ 0x20, 0x00, 0x20, 0xd4, // 8: brk #0x1 0x20, 0x00, 0x1f, 0xd6, // 12: br x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 12); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 12); EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, Analysis.validateCFIProtection(Result)); } @@ -1009,8 +1033,9 @@ 0x20, 0x00, 0x1f, 0xd6, // 20: br x1 0x20, 0x00, 0x20, 0xd4, // 24: brk #0x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 20); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 20); EXPECT_EQ(CFIProtectionStatus::PROTECTED, Analysis.validateCFIProtection(Result)); } @@ -1029,8 +1054,9 @@ 0x20, 0x00, 0x1f, 0xd6, // 24: br x1 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 24); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 24); EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, Analysis.validateCFIProtection(Result)); } @@ -1049,8 +1075,9 @@ 0x20, 0x00, 0x1f, 0xd6, // 24: br x1 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 24); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 24); 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,9 @@ // Expose this method publicly for testing. void parseSectionContents(ArrayRef SectionBytes, - uint64_t SectionAddress) { - FileAnalysis::parseSectionContents(SectionBytes, SectionAddress); + uint64_t SectionIndex, uint64_t SectionAddress) { + FileAnalysis::parseSectionContents(SectionBytes, SectionIndex, + SectionAddress); } Error initialiseDisassemblyMembers() { @@ -156,8 +157,9 @@ 0x0f, 0x0b, // 2: ud2 0xff, 0x10, // 4: callq *(%rax) }, - 0xDEADBEEF); - const auto Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); + 0x0, 0xDEADBEEF); + const auto Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 4); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1)); @@ -182,8 +184,9 @@ 0xff, 0x10, // 2: callq *(%rax) 0x0f, 0x0b, // 4: ud2 }, - 0xDEADBEEF); - const auto Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); + 0x0, 0xDEADBEEF); + const auto Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 2); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1)); @@ -211,8 +214,9 @@ 0x75, 0xf9, // 7: jne 2 [-7] 0x0f, 0x0b, // 9: ud2 }, - 0xDEADBEEF); - const auto Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); + 0x0, 0xDEADBEEF); + const auto Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 3); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2)); @@ -249,8 +253,9 @@ 0x75, 0xfb, // 5: jne 2 [-5] 0x0f, 0x0b, // 7: ud2 }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 3); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2)); @@ -284,16 +289,16 @@ 0x90, // 0: nop 0x75, 0xfe, // 1: jne 1 [-2] }, - 0xDEADBEEF); - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF); + 0x0, 0xDEADBEEF); + GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty()); - Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 1); + Result = GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 1); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty()); - Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADC0DE); + Result = GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADC0DE); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 2); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 2); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 4); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 4); 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); + 0x0, 0xDEADBEEF); uint64_t PrevSearchLengthForConditionalBranch = SearchLengthForConditionalBranch; SearchLengthForConditionalBranch = 2; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 6); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 6); 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); + 0x0, 0xDEADBEEF); uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; SearchLengthForUndef = 2; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 2); 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); + 0x0, 0xDEADBEEF); + GraphResult Result = + GraphBuilder::buildFlowGraph(Analysis, 0x0, 0xDEADBEEF + 3); EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2)); EXPECT_THAT( @@ -529,11 +541,11 @@ 0x90, // 21: nop 0x0f, 0x0b, // 22: ud2 }, - 0x1000); + 0x0, 0x1000); uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; SearchLengthForUndef = 5; - GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x1000 + 9); + GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x0, 0x1000 + 9); EXPECT_THAT(Result.OrphanedNodes, SizeIs(1)); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(3));