brintos

brintos / llvm-project-archived public Read only

0
0
Text · 44.5 KiB · 2ff7081 Raw
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