1221 lines · cpp
1//===-- LVCodeViewReader.cpp ----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This implements the LVCodeViewReader class.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h"14#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"15#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"16#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"17#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"18#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"19#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"20#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"21#include "llvm/DebugInfo/PDB/Native/DbiStream.h"22#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"23#include "llvm/DebugInfo/PDB/Native/InfoStream.h"24#include "llvm/DebugInfo/PDB/Native/LinePrinter.h"25#include "llvm/DebugInfo/PDB/Native/PDBFile.h"26#include "llvm/DebugInfo/PDB/Native/RawConstants.h"27#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"28#include "llvm/DebugInfo/PDB/Native/TpiStream.h"29#include "llvm/Object/COFF.h"30#include "llvm/Support/Errc.h"31#include "llvm/Support/Error.h"32#include "llvm/Support/FormatAdapters.h"33#include "llvm/Support/FormatVariadic.h"34#include "llvm/Support/WithColor.h"35 36using namespace llvm;37using namespace llvm::codeview;38using namespace llvm::logicalview;39using namespace llvm::msf;40using namespace llvm::object;41using namespace llvm::pdb;42 43#define DEBUG_TYPE "CodeViewReader"44 45StringRef LVCodeViewReader::getSymbolKindName(SymbolKind Kind) {46 switch (Kind) {47#define SYMBOL_RECORD(EnumName, EnumVal, Name) \48 case EnumName: \49 return #EnumName;50#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"51 default:52 return "UnknownSym";53 }54 llvm_unreachable("Unknown SymbolKind::Kind");55}56 57std::string LVCodeViewReader::formatRegisterId(RegisterId Register,58 CPUType CPU) {59#define RETURN_CASE(Enum, X, Ret) \60 case Enum::X: \61 return Ret;62 63 if (CPU == CPUType::ARMNT) {64 switch (Register) {65#define CV_REGISTERS_ARM66#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)67#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"68#undef CV_REGISTER69#undef CV_REGISTERS_ARM70 71 default:72 break;73 }74 } else if (CPU == CPUType::ARM64) {75 switch (Register) {76#define CV_REGISTERS_ARM6477#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)78#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"79#undef CV_REGISTER80#undef CV_REGISTERS_ARM6481 82 default:83 break;84 }85 } else {86 switch (Register) {87#define CV_REGISTERS_X8688#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)89#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"90#undef CV_REGISTER91#undef CV_REGISTERS_X8692 93 default:94 break;95 }96 }97 return "formatUnknownEnum(Id)";98}99 100void LVCodeViewReader::printRelocatedField(StringRef Label,101 const coff_section *CoffSection,102 uint32_t RelocOffset,103 uint32_t Offset,104 StringRef *RelocSym) {105 StringRef SymStorage;106 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;107 if (!resolveSymbolName(CoffSection, RelocOffset, Symbol))108 W.printSymbolOffset(Label, Symbol, Offset);109 else110 W.printHex(Label, RelocOffset);111}112 113void LVCodeViewReader::getLinkageName(const coff_section *CoffSection,114 uint32_t RelocOffset, uint32_t Offset,115 StringRef *RelocSym) {116 StringRef SymStorage;117 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;118 if (resolveSymbolName(CoffSection, RelocOffset, Symbol))119 Symbol = "";120}121 122Expected<StringRef>123LVCodeViewReader::getFileNameForFileOffset(uint32_t FileOffset,124 const SymbolGroup *SG) {125 if (SG) {126 Expected<StringRef> Filename = SG->getNameFromChecksums(FileOffset);127 if (!Filename) {128 consumeError(Filename.takeError());129 return StringRef("");130 }131 return *Filename;132 }133 134 // The file checksum subsection should precede all references to it.135 if (!CVFileChecksumTable.valid() || !CVStringTable.valid())136 return createStringError(object_error::parse_failed, getFileName());137 138 VarStreamArray<FileChecksumEntry>::Iterator Iter =139 CVFileChecksumTable.getArray().at(FileOffset);140 141 // Check if the file checksum table offset is valid.142 if (Iter == CVFileChecksumTable.end())143 return createStringError(object_error::parse_failed, getFileName());144 145 Expected<StringRef> NameOrErr = CVStringTable.getString(Iter->FileNameOffset);146 if (!NameOrErr)147 return createStringError(object_error::parse_failed, getFileName());148 return *NameOrErr;149}150 151Error LVCodeViewReader::printFileNameForOffset(StringRef Label,152 uint32_t FileOffset,153 const SymbolGroup *SG) {154 Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG);155 if (!NameOrErr)156 return NameOrErr.takeError();157 W.printHex(Label, *NameOrErr, FileOffset);158 return Error::success();159}160 161void LVCodeViewReader::cacheRelocations() {162 for (const SectionRef &Section : getObj().sections()) {163 const coff_section *CoffSection = getObj().getCOFFSection(Section);164 165 auto &RM = RelocMap[CoffSection];166 llvm::append_range(RM, Section.relocations());167 168 // Sort relocations by address.169 llvm::sort(RM, [](RelocationRef L, RelocationRef R) {170 return L.getOffset() < R.getOffset();171 });172 }173}174 175// Given a section and an offset into this section the function returns the176// symbol used for the relocation at the offset.177Error LVCodeViewReader::resolveSymbol(const coff_section *CoffSection,178 uint64_t Offset, SymbolRef &Sym) {179 const auto &Relocations = RelocMap[CoffSection];180 basic_symbol_iterator SymI = getObj().symbol_end();181 for (const RelocationRef &Relocation : Relocations) {182 uint64_t RelocationOffset = Relocation.getOffset();183 184 if (RelocationOffset == Offset) {185 SymI = Relocation.getSymbol();186 break;187 }188 }189 if (SymI == getObj().symbol_end())190 return make_error<StringError>("Unknown Symbol", inconvertibleErrorCode());191 Sym = *SymI;192 return ErrorSuccess();193}194 195// Given a section and an offset into this section the function returns the196// name of the symbol used for the relocation at the offset.197Error LVCodeViewReader::resolveSymbolName(const coff_section *CoffSection,198 uint64_t Offset, StringRef &Name) {199 SymbolRef Symbol;200 if (Error E = resolveSymbol(CoffSection, Offset, Symbol))201 return E;202 Expected<StringRef> NameOrErr = Symbol.getName();203 if (!NameOrErr)204 return NameOrErr.takeError();205 Name = *NameOrErr;206 return ErrorSuccess();207}208 209// CodeView and DWARF can have references to compiler generated elements,210// used for initialization. The MSVC includes in the PDBs, internal compile211// units, associated with the MS runtime support. We mark them as 'system'212// and they are printed only if the command line option 'internal=system'.213bool LVCodeViewReader::isSystemEntry(LVElement *Element, StringRef Name) const {214 Name = Name.empty() ? Element->getName() : Name;215 auto Find = [=](const char *String) -> bool { return Name.contains(String); };216 auto Starts = [=](const char *Pattern) -> bool {217 return Name.starts_with(Pattern);218 };219 auto CheckExclude = [&]() -> bool {220 if (Starts("__") || Starts("_PMD") || Starts("_PMFN"))221 return true;222 if (Find("_s__"))223 return true;224 if (Find("_CatchableType") || Find("_TypeDescriptor"))225 return true;226 if (Find("Intermediate\\vctools"))227 return true;228 if (Find("$initializer$") || Find("dynamic initializer"))229 return true;230 if (Find("`vftable'") || Find("_GLOBAL__sub"))231 return true;232 return false;233 };234 bool Excluded = CheckExclude();235 if (Excluded)236 Element->setIsSystem();237 238 return Excluded;239}240 241Error LVCodeViewReader::collectInlineeInfo(242 DebugInlineeLinesSubsectionRef &Lines, const llvm::pdb::SymbolGroup *SG) {243 for (const InlineeSourceLine &Line : Lines) {244 TypeIndex TIInlinee = Line.Header->Inlinee;245 uint32_t LineNumber = Line.Header->SourceLineNum;246 uint32_t FileOffset = Line.Header->FileID;247 LLVM_DEBUG({248 DictScope S(W, "InlineeSourceLine");249 LogicalVisitor.printTypeIndex("Inlinee", TIInlinee, StreamTPI);250 if (Error Err = printFileNameForOffset("FileID", FileOffset, SG))251 return Err;252 W.printNumber("SourceLineNum", LineNumber);253 254 if (Lines.hasExtraFiles()) {255 W.printNumber("ExtraFileCount", Line.ExtraFiles.size());256 ListScope ExtraFiles(W, "ExtraFiles");257 for (const ulittle32_t &FID : Line.ExtraFiles)258 if (Error Err = printFileNameForOffset("FileID", FID, SG))259 return Err;260 }261 });262 Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG);263 if (!NameOrErr)264 return NameOrErr.takeError();265 LogicalVisitor.addInlineeInfo(TIInlinee, LineNumber, *NameOrErr);266 }267 268 return Error::success();269}270 271Error LVCodeViewReader::traverseInlineeLines(StringRef Subsection) {272 BinaryStreamReader SR(Subsection, llvm::endianness::little);273 DebugInlineeLinesSubsectionRef Lines;274 if (Error E = Lines.initialize(SR))275 return createStringError(errorToErrorCode(std::move(E)), getFileName());276 277 return collectInlineeInfo(Lines);278}279 280Error LVCodeViewReader::createLines(281 const FixedStreamArray<LineNumberEntry> &LineNumbers, LVAddress Addendum,282 uint32_t Segment, uint32_t Begin, uint32_t Size, uint32_t NameIndex,283 const SymbolGroup *SG) {284 LLVM_DEBUG({285 uint32_t End = Begin + Size;286 W.getOStream() << formatv("{0:x-4}:{1:x-8}-{2:x-8}\n", Segment, Begin, End);287 });288 289 for (const LineNumberEntry &Line : LineNumbers) {290 if (Line.Offset >= Size)291 return createStringError(object_error::parse_failed, getFileName());292 293 LineInfo LI(Line.Flags);294 295 LLVM_DEBUG({296 W.getOStream() << formatv(297 "{0} {1:x-8}\n", utostr(LI.getStartLine()),298 fmt_align(Begin + Line.Offset, AlignStyle::Right, 8, '0'));299 });300 301 // The 'processLines()' function will move each created logical line302 // to its enclosing logical scope, using the debug ranges information303 // and they will be released when its scope parent is deleted.304 LVLineDebug *LineDebug = createLineDebug();305 CULines.push_back(LineDebug);306 LVAddress Address = linearAddress(Segment, Begin + Line.Offset);307 LineDebug->setAddress(Address + Addendum);308 309 if (LI.isAlwaysStepInto())310 LineDebug->setIsAlwaysStepInto();311 else if (LI.isNeverStepInto())312 LineDebug->setIsNeverStepInto();313 else314 LineDebug->setLineNumber(LI.getStartLine());315 316 if (LI.isStatement())317 LineDebug->setIsNewStatement();318 319 Expected<StringRef> NameOrErr = getFileNameForFileOffset(NameIndex, SG);320 if (!NameOrErr)321 return NameOrErr.takeError();322 LineDebug->setFilename(*NameOrErr);323 }324 325 return Error::success();326}327 328Error LVCodeViewReader::initializeFileAndStringTables(329 BinaryStreamReader &Reader) {330 while (Reader.bytesRemaining() > 0 &&331 (!CVFileChecksumTable.valid() || !CVStringTable.valid())) {332 // The section consists of a number of subsection in the following format:333 // |SubSectionType|SubSectionSize|Contents...|334 uint32_t SubType, SubSectionSize;335 336 if (Error E = Reader.readInteger(SubType))337 return createStringError(errorToErrorCode(std::move(E)), getFileName());338 if (Error E = Reader.readInteger(SubSectionSize))339 return createStringError(errorToErrorCode(std::move(E)), getFileName());340 341 StringRef Contents;342 if (Error E = Reader.readFixedString(Contents, SubSectionSize))343 return createStringError(errorToErrorCode(std::move(E)), getFileName());344 345 BinaryStreamRef ST(Contents, llvm::endianness::little);346 switch (DebugSubsectionKind(SubType)) {347 case DebugSubsectionKind::FileChecksums:348 if (Error E = CVFileChecksumTable.initialize(ST))349 return createStringError(errorToErrorCode(std::move(E)), getFileName());350 break;351 case DebugSubsectionKind::StringTable:352 if (Error E = CVStringTable.initialize(ST))353 return createStringError(errorToErrorCode(std::move(E)), getFileName());354 break;355 default:356 break;357 }358 359 uint32_t PaddedSize = alignTo(SubSectionSize, 4);360 if (Error E = Reader.skip(PaddedSize - SubSectionSize))361 return createStringError(errorToErrorCode(std::move(E)), getFileName());362 }363 364 return Error::success();365}366 367Error LVCodeViewReader::loadTypeServer(TypeServer2Record &TS) {368 LLVM_DEBUG({369 W.printString("Guid", formatv("{0}", TS.getGuid()).str());370 W.printNumber("Age", TS.getAge());371 W.printString("Name", TS.getName());372 });373 374 SmallString<128> ServerName(TS.getName());375 BuffOrErr = MemoryBuffer::getFile(ServerName);376 if (BuffOrErr.getError()) {377 // The server name does not exist. Try in the same directory as the378 // input file.379 ServerName = createAlternativePath(ServerName);380 BuffOrErr = MemoryBuffer::getFile(ServerName);381 if (BuffOrErr.getError()) {382 // For the error message, use the original type server name.383 return createStringError(errc::bad_file_descriptor,384 "File '%s' does not exist.",385 TS.getName().str().c_str());386 }387 }388 MemBuffer = std::move(BuffOrErr.get());389 390 // Check if the buffer corresponds to a PDB file.391 assert(identify_magic((*MemBuffer).getBuffer()) == file_magic::pdb &&392 "Invalid PDB file.");393 394 if (Error Err = loadDataForPDB(PDB_ReaderType::Native, ServerName, Session))395 return createStringError(errorToErrorCode(std::move(Err)), "%s",396 ServerName.c_str());397 398 PdbSession.reset(static_cast<NativeSession *>(Session.release()));399 PDBFile &Pdb = PdbSession->getPDBFile();400 401 // Just because a file with a matching name was found and it was an actual402 // PDB file doesn't mean it matches. For it to match the InfoStream's GUID403 // must match the GUID specified in the TypeServer2 record.404 Expected<InfoStream &> expectedInfo = Pdb.getPDBInfoStream();405 if (!expectedInfo || expectedInfo->getGuid() != TS.getGuid())406 return createStringError(errc::invalid_argument, "signature_out_of_date");407 408 // The reader needs to switch to a type server, to process the types from409 // the server. We need to keep the original input source, as reading other410 // sections will require the input associated with the loaded object file.411 TypeServer = std::make_shared<InputFile>(&Pdb);412 LogicalVisitor.setInput(TypeServer);413 414 LazyRandomTypeCollection &Types = types();415 LazyRandomTypeCollection &Ids = ids();416 if (Error Err = traverseTypes(Pdb, Types, Ids))417 return Err;418 419 return Error::success();420}421 422Error LVCodeViewReader::loadPrecompiledObject(PrecompRecord &Precomp,423 CVTypeArray &CVTypesObj) {424 LLVM_DEBUG({425 W.printHex("Count", Precomp.getTypesCount());426 W.printHex("Signature", Precomp.getSignature());427 W.printString("PrecompFile", Precomp.getPrecompFilePath());428 });429 430 SmallString<128> ServerName(Precomp.getPrecompFilePath());431 BuffOrErr = MemoryBuffer::getFile(ServerName);432 if (BuffOrErr.getError()) {433 // The server name does not exist. Try in the directory as the input file.434 ServerName = createAlternativePath(ServerName);435 if (BuffOrErr.getError()) {436 // For the error message, use the original type server name.437 return createStringError(errc::bad_file_descriptor,438 "File '%s' does not exist.",439 Precomp.getPrecompFilePath().str().c_str());440 }441 }442 MemBuffer = std::move(BuffOrErr.get());443 444 Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(*MemBuffer);445 if (errorToErrorCode(BinOrErr.takeError()))446 return createStringError(errc::not_supported,447 "Binary object format in '%s' is not supported.",448 ServerName.c_str());449 450 Binary &BinaryObj = *BinOrErr.get();451 if (!BinaryObj.isCOFF())452 return createStringError(errc::not_supported, "'%s' is not a COFF object.",453 ServerName.c_str());454 455 Builder = std::make_unique<AppendingTypeTableBuilder>(BuilderAllocator);456 457 // The MSVC precompiled header object file, should contain just a single458 // ".debug$P" section.459 COFFObjectFile &Obj = *cast<COFFObjectFile>(&BinaryObj);460 for (const SectionRef &Section : Obj.sections()) {461 Expected<StringRef> SectionNameOrErr = Section.getName();462 if (!SectionNameOrErr)463 return SectionNameOrErr.takeError();464 if (*SectionNameOrErr == ".debug$P") {465 Expected<StringRef> DataOrErr = Section.getContents();466 if (!DataOrErr)467 return DataOrErr.takeError();468 uint32_t Magic;469 if (Error Err = consume(*DataOrErr, Magic))470 return Err;471 if (Magic != COFF::DEBUG_SECTION_MAGIC)472 return errorCodeToError(object_error::parse_failed);473 474 ReaderPrecomp = std::make_unique<BinaryStreamReader>(475 *DataOrErr, llvm::endianness::little);476 cantFail(477 ReaderPrecomp->readArray(CVTypesPrecomp, ReaderPrecomp->getLength()));478 479 // Append all the type records up to the LF_ENDPRECOMP marker and480 // check if the signatures match.481 for (const CVType &Type : CVTypesPrecomp) {482 ArrayRef<uint8_t> TypeData = Type.data();483 if (Type.kind() == LF_ENDPRECOMP) {484 EndPrecompRecord EndPrecomp = cantFail(485 TypeDeserializer::deserializeAs<EndPrecompRecord>(TypeData));486 if (Precomp.getSignature() != EndPrecomp.getSignature())487 return createStringError(errc::invalid_argument, "no matching pch");488 break;489 }490 Builder->insertRecordBytes(TypeData);491 }492 // Done processing .debug$P, break out of section loop.493 break;494 }495 }496 497 // Append all the type records, skipping the first record which is the498 // reference to the precompiled header object information.499 for (const CVType &Type : CVTypesObj) {500 ArrayRef<uint8_t> TypeData = Type.data();501 if (Type.kind() != LF_PRECOMP)502 Builder->insertRecordBytes(TypeData);503 }504 505 // Set up a type stream that refers to the added type records.506 Builder->ForEachRecord(507 [&](TypeIndex TI, const CVType &Type) { TypeArray.push_back(Type); });508 509 ItemStream =510 std::make_unique<BinaryItemStream<CVType>>(llvm::endianness::little);511 ItemStream->setItems(TypeArray);512 TypeStream.setUnderlyingStream(*ItemStream);513 514 PrecompHeader =515 std::make_shared<LazyRandomTypeCollection>(TypeStream, TypeArray.size());516 517 // Change the original input source to use the collected type records.518 LogicalVisitor.setInput(PrecompHeader);519 520 LazyRandomTypeCollection &Types = types();521 LazyRandomTypeCollection &Ids = ids();522 LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI,523 LogicalVisitor.getShared());524 return visitTypeStream(Types, TDV);525}526 527Error LVCodeViewReader::traverseTypeSection(StringRef SectionName,528 const SectionRef &Section) {529 LLVM_DEBUG({530 ListScope D(W, "CodeViewTypes");531 W.printNumber("Section", SectionName, getObj().getSectionID(Section));532 });533 534 Expected<StringRef> DataOrErr = Section.getContents();535 if (!DataOrErr)536 return DataOrErr.takeError();537 uint32_t Magic;538 if (Error Err = consume(*DataOrErr, Magic))539 return Err;540 if (Magic != COFF::DEBUG_SECTION_MAGIC)541 return errorCodeToError(object_error::parse_failed);542 543 // Get the first type record. It will indicate if this object uses a type544 // server (/Zi) or a PCH file (/Yu).545 CVTypeArray CVTypes;546 BinaryStreamReader Reader(*DataOrErr, llvm::endianness::little);547 cantFail(Reader.readArray(CVTypes, Reader.getLength()));548 CVTypeArray::Iterator FirstType = CVTypes.begin();549 550 // The object was compiled with /Zi. It uses types from a type server PDB.551 if (FirstType->kind() == LF_TYPESERVER2) {552 TypeServer2Record TS = cantFail(553 TypeDeserializer::deserializeAs<TypeServer2Record>(FirstType->data()));554 return loadTypeServer(TS);555 }556 557 // The object was compiled with /Yc or /Yu. It uses types from another558 // object file with a matching signature.559 if (FirstType->kind() == LF_PRECOMP) {560 PrecompRecord Precomp = cantFail(561 TypeDeserializer::deserializeAs<PrecompRecord>(FirstType->data()));562 return loadPrecompiledObject(Precomp, CVTypes);563 }564 565 LazyRandomTypeCollection &Types = types();566 LazyRandomTypeCollection &Ids = ids();567 Types.reset(*DataOrErr, 100);568 LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI,569 LogicalVisitor.getShared());570 return visitTypeStream(Types, TDV);571}572 573Error LVCodeViewReader::traverseTypes(PDBFile &Pdb,574 LazyRandomTypeCollection &Types,575 LazyRandomTypeCollection &Ids) {576 // Traverse types (TPI and IPI).577 auto VisitTypes = [&](LazyRandomTypeCollection &Types,578 LazyRandomTypeCollection &Ids,579 SpecialStream StreamIdx) -> Error {580 LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamIdx,581 LogicalVisitor.getShared());582 return visitTypeStream(Types, TDV);583 };584 585 Expected<TpiStream &> StreamTpiOrErr = Pdb.getPDBTpiStream();586 if (!StreamTpiOrErr)587 return StreamTpiOrErr.takeError();588 TpiStream &StreamTpi = *StreamTpiOrErr;589 StreamTpi.buildHashMap();590 LLVM_DEBUG({591 W.getOStream() << formatv("Showing {0:N} TPI records\n",592 StreamTpi.getNumTypeRecords());593 });594 if (Error Err = VisitTypes(Types, Ids, StreamTPI))595 return Err;596 597 Expected<TpiStream &> StreamIpiOrErr = Pdb.getPDBIpiStream();598 if (!StreamIpiOrErr)599 return StreamIpiOrErr.takeError();600 TpiStream &StreamIpi = *StreamIpiOrErr;601 StreamIpi.buildHashMap();602 LLVM_DEBUG({603 W.getOStream() << formatv("Showing {0:N} IPI records\n",604 StreamIpi.getNumTypeRecords());605 });606 return VisitTypes(Ids, Ids, StreamIPI);607}608 609Error LVCodeViewReader::traverseSymbolsSubsection(StringRef Subsection,610 const SectionRef &Section,611 StringRef SectionContents) {612 ArrayRef<uint8_t> BinaryData(Subsection.bytes_begin(),613 Subsection.bytes_end());614 LVSymbolVisitorDelegate VisitorDelegate(this, Section, &getObj(),615 SectionContents);616 CVSymbolArray Symbols;617 BinaryStreamReader Reader(BinaryData, llvm::endianness::little);618 if (Error E = Reader.readArray(Symbols, Reader.getLength()))619 return createStringError(errorToErrorCode(std::move(E)), getFileName());620 621 LazyRandomTypeCollection &Types = types();622 LazyRandomTypeCollection &Ids = ids();623 SymbolVisitorCallbackPipeline Pipeline;624 SymbolDeserializer Deserializer(&VisitorDelegate,625 CodeViewContainer::ObjectFile);626 // As we are processing a COFF format, use TPI as IPI, so the generic code627 // to process the CodeView format does not contain any additional checks.628 LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids,629 &VisitorDelegate, LogicalVisitor.getShared());630 631 Pipeline.addCallbackToPipeline(Deserializer);632 Pipeline.addCallbackToPipeline(Traverser);633 CVSymbolVisitor Visitor(Pipeline);634 return Visitor.visitSymbolStream(Symbols);635}636 637Error LVCodeViewReader::traverseSymbolSection(StringRef SectionName,638 const SectionRef &Section) {639 LLVM_DEBUG({640 ListScope D(W, "CodeViewDebugInfo");641 W.printNumber("Section", SectionName, getObj().getSectionID(Section));642 });643 644 Expected<StringRef> SectionOrErr = Section.getContents();645 if (!SectionOrErr)646 return SectionOrErr.takeError();647 StringRef SectionContents = *SectionOrErr;648 StringRef Data = SectionContents;649 650 SmallVector<StringRef, 10> SymbolNames;651 StringMap<StringRef> FunctionLineTables;652 653 uint32_t Magic;654 if (Error E = consume(Data, Magic))655 return createStringError(errorToErrorCode(std::move(E)), getFileName());656 657 if (Magic != COFF::DEBUG_SECTION_MAGIC)658 return createStringError(object_error::parse_failed, getFileName());659 660 BinaryStreamReader FSReader(Data, llvm::endianness::little);661 if (Error Err = initializeFileAndStringTables(FSReader))662 return Err;663 664 while (!Data.empty()) {665 // The section consists of a number of subsection in the following format:666 // |SubSectionType|SubSectionSize|Contents...|667 uint32_t SubType, SubSectionSize;668 if (Error E = consume(Data, SubType))669 return createStringError(errorToErrorCode(std::move(E)), getFileName());670 if (Error E = consume(Data, SubSectionSize))671 return createStringError(errorToErrorCode(std::move(E)), getFileName());672 673 // Process the subsection as normal even if the ignore bit is set.674 SubType &= ~SubsectionIgnoreFlag;675 676 // Get the contents of the subsection.677 if (SubSectionSize > Data.size())678 return createStringError(object_error::parse_failed, getFileName());679 StringRef Contents = Data.substr(0, SubSectionSize);680 681 // Add SubSectionSize to the current offset and align that offset682 // to find the next subsection.683 size_t SectionOffset = Data.data() - SectionContents.data();684 size_t NextOffset = SectionOffset + SubSectionSize;685 NextOffset = alignTo(NextOffset, 4);686 if (NextOffset > SectionContents.size())687 return createStringError(object_error::parse_failed, getFileName());688 Data = SectionContents.drop_front(NextOffset);689 690 switch (DebugSubsectionKind(SubType)) {691 case DebugSubsectionKind::Symbols:692 if (Error Err =693 traverseSymbolsSubsection(Contents, Section, SectionContents))694 return Err;695 break;696 697 case DebugSubsectionKind::InlineeLines:698 if (Error Err = traverseInlineeLines(Contents))699 return Err;700 break;701 702 case DebugSubsectionKind::Lines:703 // Holds a PC to file:line table. Some data to parse this subsection704 // is stored in the other subsections, so just check sanity and store705 // the pointers for deferred processing.706 707 // Collect function and ranges only if we need to print logical lines.708 if (options().getGeneralCollectRanges()) {709 710 if (SubSectionSize < 12) {711 // There should be at least three words to store two function712 // relocations and size of the code.713 return createStringError(object_error::parse_failed, getFileName());714 }715 716 StringRef SymbolName;717 if (Error Err = resolveSymbolName(getObj().getCOFFSection(Section),718 SectionOffset, SymbolName))719 return createStringError(errorToErrorCode(std::move(Err)),720 getFileName());721 722 LLVM_DEBUG({ W.printString("Symbol Name", SymbolName); });723 if (!FunctionLineTables.try_emplace(SymbolName, Contents).second) {724 // Saw debug info for this function already?725 return createStringError(object_error::parse_failed, getFileName());726 }727 728 SymbolNames.push_back(SymbolName);729 }730 break;731 732 // Do nothing for unrecognized subsections.733 default:734 break;735 }736 W.flush();737 }738 739 // Traverse the line tables now that we've read all the subsections and740 // know all the required information.741 for (StringRef SymbolName : SymbolNames) {742 LLVM_DEBUG({743 ListScope S(W, "FunctionLineTable");744 W.printString("Symbol Name", SymbolName);745 });746 747 BinaryStreamReader Reader(FunctionLineTables[SymbolName],748 llvm::endianness::little);749 750 DebugLinesSubsectionRef Lines;751 if (Error E = Lines.initialize(Reader))752 return createStringError(errorToErrorCode(std::move(E)), getFileName());753 754 // Find the associated symbol table information.755 LVSymbolTableEntry SymbolTableEntry = getSymbolTableEntry(SymbolName);756 LVScope *Function = SymbolTableEntry.Scope;757 if (!Function)758 continue;759 760 LVAddress Addendum = SymbolTableEntry.Address;761 LVSectionIndex SectionIndex = SymbolTableEntry.SectionIndex;762 763 // The given scope represents the function that contains the line numbers.764 // Collect all generated debug lines associated with the function.765 CULines.clear();766 767 // For the given scope, collect all scopes ranges.768 LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);769 ScopesWithRanges->clear();770 Function->getRanges(*ScopesWithRanges);771 ScopesWithRanges->sort();772 773 uint16_t Segment = Lines.header()->RelocSegment;774 uint32_t Begin = Lines.header()->RelocOffset;775 uint32_t Size = Lines.header()->CodeSize;776 for (const LineColumnEntry &Block : Lines)777 if (Error Err = createLines(Block.LineNumbers, Addendum, Segment, Begin,778 Size, Block.NameIndex))779 return Err;780 781 // Include lines from any inlined functions within the current function.782 includeInlineeLines(SectionIndex, Function);783 784 if (Error Err = createInstructions(Function, SectionIndex))785 return Err;786 787 processLines(&CULines, SectionIndex, Function);788 }789 790 return Error::success();791}792 793void LVCodeViewReader::sortScopes() { Root->sort(); }794 795void LVCodeViewReader::print(raw_ostream &OS) const {796 LLVM_DEBUG(dbgs() << "CreateReaders\n");797}798 799void LVCodeViewReader::mapRangeAddress(const ObjectFile &Obj,800 const SectionRef &Section,801 bool IsComdat) {802 if (!Obj.isCOFF())803 return;804 805 const COFFObjectFile *Object = cast<COFFObjectFile>(&Obj);806 807 for (const SymbolRef &Sym : Object->symbols()) {808 if (!Section.containsSymbol(Sym))809 continue;810 811 COFFSymbolRef Symbol = Object->getCOFFSymbol(Sym);812 if (Symbol.getComplexType() != llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION)813 continue;814 815 StringRef SymbolName;816 Expected<StringRef> SymNameOrErr = Object->getSymbolName(Symbol);817 if (!SymNameOrErr) {818 W.startLine() << "Invalid symbol name: " << Symbol.getSectionNumber()819 << "\n";820 consumeError(SymNameOrErr.takeError());821 continue;822 }823 SymbolName = *SymNameOrErr;824 825 LLVM_DEBUG({826 Expected<const coff_section *> SectionOrErr =827 Object->getSection(Symbol.getSectionNumber());828 if (!SectionOrErr) {829 W.startLine() << "Invalid section number: " << Symbol.getSectionNumber()830 << "\n";831 consumeError(SectionOrErr.takeError());832 return;833 }834 W.printNumber("Section #", Symbol.getSectionNumber());835 W.printString("Name", SymbolName);836 W.printHex("Value", Symbol.getValue());837 });838 839 // Record the symbol name (linkage) and its loading address.840 addToSymbolTable(SymbolName, Symbol.getValue(), Symbol.getSectionNumber(),841 IsComdat);842 }843}844 845Error LVCodeViewReader::createScopes(COFFObjectFile &Obj) {846 if (Error Err = loadTargetInfo(Obj))847 return Err;848 849 // Initialization required when processing a COFF file:850 // Cache the symbols relocations.851 // Create a mapping for virtual addresses.852 // Get the functions entry points.853 cacheRelocations();854 mapVirtualAddress(Obj);855 856 for (const SectionRef &Section : Obj.sections()) {857 Expected<StringRef> SectionNameOrErr = Section.getName();858 if (!SectionNameOrErr)859 return SectionNameOrErr.takeError();860 // .debug$T is a standard CodeView type section, while .debug$P is the861 // same format but used for MSVC precompiled header object files.862 if (*SectionNameOrErr == ".debug$T" || *SectionNameOrErr == ".debug$P")863 if (Error Err = traverseTypeSection(*SectionNameOrErr, Section))864 return Err;865 }866 867 // Process collected namespaces.868 LogicalVisitor.processNamespaces();869 870 for (const SectionRef &Section : Obj.sections()) {871 Expected<StringRef> SectionNameOrErr = Section.getName();872 if (!SectionNameOrErr)873 return SectionNameOrErr.takeError();874 if (*SectionNameOrErr == ".debug$S")875 if (Error Err = traverseSymbolSection(*SectionNameOrErr, Section))876 return Err;877 }878 879 // Check if we have to close the Compile Unit scope.880 LogicalVisitor.closeScope();881 882 // Traverse the strings recorded and transform them into filenames.883 LogicalVisitor.processFiles();884 885 // Process collected element lines.886 LogicalVisitor.processLines();887 888 // Translate composite names into a single component.889 Root->transformScopedName();890 return Error::success();891}892 893Error LVCodeViewReader::createScopes(PDBFile &Pdb) {894 if (Error Err = loadTargetInfo(Pdb))895 return Err;896 897 if (!Pdb.hasPDBTpiStream() || !Pdb.hasPDBDbiStream())898 return Error::success();899 900 // Open the executable associated with the PDB file and get the section901 // addresses used to calculate linear addresses for CodeView Symbols.902 if (!ExePath.empty()) {903 ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =904 MemoryBuffer::getFileOrSTDIN(ExePath);905 if (BuffOrErr.getError()) {906 return createStringError(errc::bad_file_descriptor,907 "File '%s' does not exist.", ExePath.c_str());908 }909 BinaryBuffer = std::move(BuffOrErr.get());910 911 // Check if the buffer corresponds to a PECOFF executable.912 assert(identify_magic(BinaryBuffer->getBuffer()) ==913 file_magic::pecoff_executable &&914 "Invalid PECOFF executable file.");915 916 Expected<std::unique_ptr<Binary>> BinOrErr =917 createBinary(BinaryBuffer->getMemBufferRef());918 if (errorToErrorCode(BinOrErr.takeError())) {919 return createStringError(errc::not_supported,920 "Binary object format in '%s' is not supported.",921 ExePath.c_str());922 }923 BinaryExecutable = std::move(*BinOrErr);924 if (COFFObjectFile *COFFObject =925 dyn_cast<COFFObjectFile>(BinaryExecutable.get()))926 mapVirtualAddress(*COFFObject);927 }928 929 // In order to generate a full logical view, we have to traverse both930 // streams TPI and IPI if they are present. The following table gives931 // the stream where a specified type is located. If the IPI stream is932 // not present, all the types are located in the TPI stream.933 //934 // TPI Stream:935 // LF_POINTER LF_MODIFIER LF_PROCEDURE LF_MFUNCTION936 // LF_LABEL LF_ARGLIST LF_FIELDLIST LF_ARRAY937 // LF_CLASS LF_STRUCTURE LF_INTERFACE LF_UNION938 // LF_ENUM LF_TYPESERVER2 LF_VFTABLE LF_VTSHAPE939 // LF_BITFIELD LF_METHODLIST LF_PRECOMP LF_ENDPRECOMP940 //941 // IPI stream:942 // LF_FUNC_ID LF_MFUNC_ID LF_BUILDINFO943 // LF_SUBSTR_LIST LF_STRING_ID LF_UDT_SRC_LINE944 // LF_UDT_MOD_SRC_LINE945 946 LazyRandomTypeCollection &Types = types();947 LazyRandomTypeCollection &Ids = ids();948 if (Error Err = traverseTypes(Pdb, Types, Ids))949 return Err;950 951 // Process collected namespaces.952 LogicalVisitor.processNamespaces();953 954 LLVM_DEBUG({ W.getOStream() << "Traversing inlined lines\n"; });955 956 auto VisitInlineeLines = [&](int32_t Modi, const SymbolGroup &SG,957 DebugInlineeLinesSubsectionRef &Lines) -> Error {958 return collectInlineeInfo(Lines, &SG);959 };960 961 FilterOptions Filters = {};962 LinePrinter Printer(/*Indent=*/2, false, nulls(), Filters);963 const PrintScope HeaderScope(Printer, /*IndentLevel=*/2);964 if (Error Err = iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(965 Input, HeaderScope, VisitInlineeLines))966 return Err;967 968 // Traverse global symbols.969 LLVM_DEBUG({ W.getOStream() << "Traversing global symbols\n"; });970 if (Pdb.hasPDBGlobalsStream()) {971 Expected<GlobalsStream &> GlobalsOrErr = Pdb.getPDBGlobalsStream();972 if (!GlobalsOrErr)973 return GlobalsOrErr.takeError();974 GlobalsStream &Globals = *GlobalsOrErr;975 const GSIHashTable &Table = Globals.getGlobalsTable();976 Expected<SymbolStream &> ExpectedSyms = Pdb.getPDBSymbolStream();977 if (ExpectedSyms) {978 979 SymbolVisitorCallbackPipeline Pipeline;980 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);981 LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,982 LogicalVisitor.getShared());983 984 // As the global symbols do not have an associated Compile Unit, create985 // one, as the container for all global symbols.986 RecordPrefix Prefix(SymbolKind::S_COMPILE3);987 CVSymbol Symbol(&Prefix, sizeof(Prefix));988 uint32_t Offset = 0;989 if (Error Err = Traverser.visitSymbolBegin(Symbol, Offset))990 consumeError(std::move(Err));991 else {992 // The CodeView compile unit containing the global symbols does not993 // have a name; generate one using its parent name (object filename)994 // follow by the '_global' string.995 std::string Name(CompileUnit->getParentScope()->getName());996 CompileUnit->setName(Name.append("_global"));997 998 Pipeline.addCallbackToPipeline(Deserializer);999 Pipeline.addCallbackToPipeline(Traverser);1000 CVSymbolVisitor Visitor(Pipeline);1001 1002 BinaryStreamRef SymStream =1003 ExpectedSyms->getSymbolArray().getUnderlyingStream();1004 for (uint32_t PubSymOff : Table) {1005 Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);1006 if (Sym) {1007 if (Error Err = Visitor.visitSymbolRecord(*Sym, PubSymOff))1008 return createStringError(errorToErrorCode(std::move(Err)),1009 getFileName());1010 } else {1011 consumeError(Sym.takeError());1012 }1013 }1014 }1015 1016 LogicalVisitor.closeScope();1017 } else {1018 consumeError(ExpectedSyms.takeError());1019 }1020 }1021 1022 // Traverse symbols (DBI).1023 LLVM_DEBUG({ W.getOStream() << "Traversing symbol groups\n"; });1024 1025 auto VisitSymbolGroup = [&](uint32_t Modi, const SymbolGroup &SG) -> Error {1026 Expected<ModuleDebugStreamRef> ExpectedModS =1027 getModuleDebugStream(Pdb, Modi);1028 if (ExpectedModS) {1029 ModuleDebugStreamRef &ModS = *ExpectedModS;1030 1031 LLVM_DEBUG({1032 W.getOStream() << formatv("Traversing Group: Mod {0:4}\n", Modi);1033 });1034 1035 SymbolVisitorCallbackPipeline Pipeline;1036 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);1037 LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,1038 LogicalVisitor.getShared());1039 1040 Pipeline.addCallbackToPipeline(Deserializer);1041 Pipeline.addCallbackToPipeline(Traverser);1042 CVSymbolVisitor Visitor(Pipeline);1043 BinarySubstreamRef SS = ModS.getSymbolsSubstream();1044 if (Error Err =1045 Visitor.visitSymbolStream(ModS.getSymbolArray(), SS.Offset))1046 return createStringError(errorToErrorCode(std::move(Err)),1047 getFileName());1048 } else {1049 // If the module stream does not exist, it is not an error condition.1050 consumeError(ExpectedModS.takeError());1051 }1052 1053 return Error::success();1054 };1055 1056 if (Error Err = iterateSymbolGroups(Input, HeaderScope, VisitSymbolGroup))1057 return Err;1058 1059 // At this stage, the logical view contains all scopes, symbols and types.1060 // For PDBs we can use the module id, to access its specific compile unit.1061 // The line record addresses has been already resolved, so we can apply the1062 // flow as when processing DWARF.1063 1064 LLVM_DEBUG({ W.getOStream() << "Traversing lines\n"; });1065 1066 // Record all line records for a Compile Unit.1067 CULines.clear();1068 1069 auto VisitDebugLines = [this](int32_t Modi, const SymbolGroup &SG,1070 DebugLinesSubsectionRef &Lines) -> Error {1071 if (!options().getPrintLines())1072 return Error::success();1073 1074 uint16_t Segment = Lines.header()->RelocSegment;1075 uint32_t Begin = Lines.header()->RelocOffset;1076 uint32_t Size = Lines.header()->CodeSize;1077 1078 LLVM_DEBUG({ W.getOStream() << formatv("Modi = {0}\n", Modi); });1079 1080 // We have line information for a new module; finish processing the1081 // collected information for the current module. Once it is done, start1082 // recording the line information for the new module.1083 if (CurrentModule != Modi) {1084 if (Error Err = processModule())1085 return Err;1086 CULines.clear();1087 CurrentModule = Modi;1088 }1089 1090 for (const LineColumnEntry &Block : Lines)1091 if (Error Err = createLines(Block.LineNumbers, /*Addendum=*/0, Segment,1092 Begin, Size, Block.NameIndex, &SG))1093 return Err;1094 1095 return Error::success();1096 };1097 1098 if (Error Err = iterateModuleSubsections<DebugLinesSubsectionRef>(1099 Input, HeaderScope, VisitDebugLines))1100 return Err;1101 1102 // Check if we have to close the Compile Unit scope.1103 LogicalVisitor.closeScope();1104 1105 // Process collected element lines.1106 LogicalVisitor.processLines();1107 1108 // Translate composite names into a single component.1109 Root->transformScopedName();1110 return Error::success();1111}1112 1113Error LVCodeViewReader::processModule() {1114 if (LVScope *Scope = getScopeForModule(CurrentModule)) {1115 CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);1116 1117 LLVM_DEBUG({ dbgs() << "Processing Scope: " << Scope->getName() << "\n"; });1118 1119 // For the given compile unit, collect all scopes ranges.1120 // For a complete ranges and lines mapping, the logical view support1121 // needs for the compile unit to have a low and high pc values. We1122 // can traverse the 'Modules' section and get the information for the1123 // specific module. Another option, is from all the ranges collected1124 // to take the first and last values.1125 LVSectionIndex SectionIndex = DotTextSectionIndex;1126 LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);1127 ScopesWithRanges->clear();1128 CompileUnit->getRanges(*ScopesWithRanges);1129 if (!ScopesWithRanges->empty())1130 CompileUnit->addObject(ScopesWithRanges->getLower(),1131 ScopesWithRanges->getUpper());1132 ScopesWithRanges->sort();1133 1134 if (Error Err = createInstructions())1135 return Err;1136 1137 // Include lines from any inlined functions within the current function.1138 includeInlineeLines(SectionIndex, Scope);1139 1140 processLines(&CULines, SectionIndex, nullptr);1141 }1142 1143 return Error::success();1144}1145 1146// In order to create the scopes, the CodeView Reader will:1147// = Traverse the TPI/IPI stream (Type visitor):1148// Collect forward references, scoped names, type indexes that will represent1149// a logical element, strings, line records, linkage names.1150// = Traverse the symbols section (Symbol visitor):1151// Create the scopes tree and creates the required logical elements, by1152// using the collected indexes from the type visitor.1153Error LVCodeViewReader::createScopes() {1154 LLVM_DEBUG({1155 W.startLine() << "\n";1156 W.printString("File", getFileName().str());1157 W.printString("Exe", ExePath);1158 W.printString("Format", FileFormatName);1159 });1160 1161 if (Error Err = LVReader::createScopes())1162 return Err;1163 1164 LogicalVisitor.setRoot(Root);1165 1166 if (isObj()) {1167 if (Error Err = createScopes(getObj()))1168 return Err;1169 } else {1170 if (Error Err = createScopes(getPdb()))1171 return Err;1172 }1173 1174 return Error::success();1175}1176 1177Error LVCodeViewReader::loadTargetInfo(const ObjectFile &Obj) {1178 // Detect the architecture from the object file. We usually don't need OS1179 // info to lookup a target and create register info.1180 Triple TT;1181 TT.setArch(Triple::ArchType(Obj.getArch()));1182 TT.setVendor(Triple::UnknownVendor);1183 TT.setOS(Triple::UnknownOS);1184 1185 // Features to be passed to target/subtarget1186 Expected<SubtargetFeatures> Features = Obj.getFeatures();1187 SubtargetFeatures FeaturesValue;1188 if (!Features) {1189 consumeError(Features.takeError());1190 FeaturesValue = SubtargetFeatures();1191 }1192 FeaturesValue = *Features;1193 1194 StringRef CPU;1195 if (auto OptCPU = Obj.tryGetCPUName())1196 CPU = *OptCPU;1197 1198 return loadGenericTargetInfo(TT.str(), FeaturesValue.getString(), CPU);1199}1200 1201Error LVCodeViewReader::loadTargetInfo(const PDBFile &Pdb) {1202 Triple TT;1203 TT.setArch(Triple::ArchType::x86_64);1204 TT.setVendor(Triple::UnknownVendor);1205 TT.setOS(Triple::Win32);1206 1207 StringRef TheFeature = "";1208 StringRef TheCPU = "";1209 1210 return loadGenericTargetInfo(TT.str(), TheFeature, TheCPU);1211}1212 1213std::string LVCodeViewReader::getRegisterName(LVSmall Opcode,1214 ArrayRef<uint64_t> Operands) {1215 // Get Compilation Unit CPU Type.1216 CPUType CPU = getCompileUnitCPUType();1217 // For CodeView the register always is in Operands[0];1218 RegisterId Register = (RegisterId(Operands[0]));1219 return formatRegisterId(Register, CPU);1220}1221