//===- DebugTypes.h ---------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLD_COFF_DEBUGTYPES_H #define LLD_COFF_DEBUGTYPES_H #include "lld/Common/LLVM.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" namespace llvm { namespace codeview { struct GloballyHashedType; } // namespace codeview namespace pdb { class NativeSession; class TpiStream; } } // namespace llvm namespace lld { namespace coff { using llvm::codeview::GloballyHashedType; using llvm::codeview::TypeIndex; class ObjFile; class PDBInputFile; class TypeMerger; struct GHashState; class TpiSource { public: enum TpiKind : uint8_t { Regular, PCH, UsingPCH, PDB, PDBIpi, UsingPDB }; TpiSource(TpiKind k, ObjFile *f); virtual ~TpiSource(); /// Produce a mapping from the type and item indices used in the object /// file to those in the destination PDB. /// /// If the object file uses a type server PDB (compiled with /Zi), merge TPI /// and IPI from the type server PDB and return a map for it. Each unique type /// server PDB is merged at most once, so this may return an existing index /// mapping. /// /// If the object does not use a type server PDB (compiled with /Z7), we merge /// all the type and item records from the .debug$S stream and fill in the /// caller-provided ObjectIndexMap. virtual Error mergeDebugT(TypeMerger *m); /// Load global hashes, either by hashing types directly, or by loading them /// from LLVM's .debug$H section. virtual void loadGHashes(); /// Use global hashes to merge type information. virtual void remapTpiWithGHashes(GHashState *g); // Remap a type index in place. bool remapTypeIndex(TypeIndex &ti, llvm::codeview::TiRefKind refKind) const; protected: void remapRecord(MutableArrayRef rec, ArrayRef typeRefs); void mergeTypeRecord(TypeIndex curIndex, llvm::codeview::CVType ty); // Merge the type records listed in uniqueTypes. beginIndex is the TypeIndex // of the first record in this source, typically 0x1000. When PCHs are // involved, it may start higher. void mergeUniqueTypeRecords( ArrayRef debugTypes, TypeIndex beginIndex = TypeIndex(TypeIndex::FirstNonSimpleIndex)); // Use the ghash table to construct a map from source type index to // destination PDB type index. Usable for either TPI or IPI. void fillMapFromGHashes(GHashState *m, llvm::SmallVectorImpl &indexMap); // Copies ghashes from a vector into an array. These are long lived, so it's // worth the time to copy these into an appropriately sized vector to reduce // memory usage. void assignGHashesFromVector(std::vector &&hashVec); // Walk over file->debugTypes and fill in the isItemIndex bit vector. void fillIsItemIndexFromDebugT(); public: bool remapTypesInSymbolRecord(MutableArrayRef rec); void remapTypesInTypeRecord(MutableArrayRef rec); /// Is this a dependent file that needs to be processed first, before other /// OBJs? virtual bool isDependency() const { return false; } /// Returns true if this type record should be omitted from the PDB, even if /// it is unique. This prevents a record from being added to the input ghash /// table. bool shouldOmitFromPdb(uint32_t ghashIdx) { return ghashIdx == endPrecompGHashIdx; } /// All sources of type information in the program. static std::vector instances; /// Dependency type sources, such as type servers or PCH object files. These /// must be processed before objects that rely on them. Set by /// TpiSources::sortDependencies. static ArrayRef dependencySources; /// Object file sources. These must be processed after dependencySources. static ArrayRef objectSources; /// Sorts the dependencies and reassigns TpiSource indices. static void sortDependencies(); static uint32_t countTypeServerPDBs(); static uint32_t countPrecompObjs(); /// Free heap allocated ghashes. static void clearGHashes(); /// Clear global data structures for TpiSources. static void clear(); const TpiKind kind; bool ownedGHashes = true; uint32_t tpiSrcIdx = 0; protected: /// The ghash index (zero based, not 0x1000-based) of the LF_ENDPRECOMP record /// in this object, if one exists. This is the all ones value otherwise. It is /// recorded here so that it can be omitted from the final ghash table. uint32_t endPrecompGHashIdx = ~0U; public: ObjFile *file; /// An error encountered during type merging, if any. Error typeMergingError = Error::success(); // Storage for tpiMap or ipiMap, depending on the kind of source. llvm::SmallVector indexMapStorage; // Source type index to PDB type index mapping for type and item records. // These mappings will be the same for /Z7 objects, and distinct for /Zi // objects. llvm::ArrayRef tpiMap; llvm::ArrayRef ipiMap; /// Array of global type hashes, indexed by TypeIndex. May be calculated on /// demand, or present in input object files. llvm::ArrayRef ghashes; /// When ghashing is used, record the mapping from LF_[M]FUNC_ID to function /// type index here. Both indices are PDB indices, not object type indexes. std::vector> funcIdToType; /// Indicates if a type record is an item index or a type index. llvm::BitVector isItemIndex; /// A list of all "unique" type indices which must be merged into the final /// PDB. GHash type deduplication produces this list, and it should be /// considerably smaller than the input. std::vector uniqueTypes; struct MergedInfo { std::vector recs; std::vector recSizes; std::vector recHashes; }; MergedInfo mergedTpi; MergedInfo mergedIpi; uint64_t nbTypeRecords = 0; uint64_t nbTypeRecordsBytes = 0; }; TpiSource *makeTpiSource(ObjFile *file); TpiSource *makeTypeServerSource(PDBInputFile *pdbInputFile); TpiSource *makeUseTypeServerSource(ObjFile *file, llvm::codeview::TypeServer2Record ts); TpiSource *makePrecompSource(ObjFile *file); TpiSource *makeUsePrecompSource(ObjFile *file, llvm::codeview::PrecompRecord ts); } // namespace coff } // namespace lld #endif