1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
//===- 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::codeview {
struct GloballyHashedType;
}
namespace llvm::pdb {
class NativeSession;
class TpiStream;
}
namespace lld::coff {
using llvm::codeview::GloballyHashedType;
using llvm::codeview::TypeIndex;
class ObjFile;
class PDBInputFile;
class TypeMerger;
struct GHashState;
class COFFLinkerContext;
class TpiSource {
public:
enum TpiKind : uint8_t { Regular, PCH, UsingPCH, PDB, PDBIpi, UsingPDB };
TpiSource(COFFLinkerContext &ctx, 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<uint8_t> rec,
ArrayRef<llvm::codeview::TiReference> 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<uint8_t> 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);
// 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<GloballyHashedType> &&hashVec);
// Walk over file->debugTypes and fill in the isItemIndex bit vector.
void fillIsItemIndexFromDebugT();
COFFLinkerContext &ctx;
public:
bool remapTypesInSymbolRecord(MutableArrayRef<uint8_t> rec);
void remapTypesInTypeRecord(MutableArrayRef<uint8_t> 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 == endPrecompIdx;
}
const TpiKind kind;
bool ownedGHashes = true;
uint32_t tpiSrcIdx = 0;
/// The 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 for validation, and so that it can be omitted from the final
/// ghash table.
uint32_t endPrecompIdx = ~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<TypeIndex, 0> 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<TypeIndex> tpiMap;
llvm::ArrayRef<TypeIndex> ipiMap;
/// Array of global type hashes, indexed by TypeIndex. May be calculated on
/// demand, or present in input object files.
llvm::ArrayRef<llvm::codeview::GloballyHashedType> 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<std::pair<TypeIndex, TypeIndex>> 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<uint32_t> uniqueTypes;
struct MergedInfo {
std::vector<uint8_t> recs;
std::vector<uint16_t> recSizes;
std::vector<uint32_t> recHashes;
};
MergedInfo mergedTpi;
MergedInfo mergedIpi;
uint64_t nbTypeRecords = 0;
uint64_t nbTypeRecordsBytes = 0;
};
TpiSource *makeTpiSource(COFFLinkerContext &ctx, ObjFile *f);
TpiSource *makeTypeServerSource(COFFLinkerContext &ctx,
PDBInputFile *pdbInputFile);
TpiSource *makeUseTypeServerSource(COFFLinkerContext &ctx, ObjFile *file,
llvm::codeview::TypeServer2Record ts);
TpiSource *makePrecompSource(COFFLinkerContext &ctx, ObjFile *file);
TpiSource *makeUsePrecompSource(COFFLinkerContext &ctx, ObjFile *file,
llvm::codeview::PrecompRecord ts);
} // namespace lld::coff
#endif
|