clang 20.0.0 (based on r547379) from build 12806354. Bug: http://b/379133546 Test: N/A Change-Id: I2eb8938af55d809de674be63cb30cf27e801862b Upstream-Commit: ad834e67b1105d15ef907f6255d4c96e8e733f57
231 lines
6.9 KiB
C++
231 lines
6.9 KiB
C++
//===- InputFile.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 LLVM_DEBUGINFO_PDB_NATIVE_INPUTFILE_H
|
|
#define LLVM_DEBUGINFO_PDB_NATIVE_INPUTFILE_H
|
|
|
|
#include "llvm/ADT/PointerUnion.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
#include "llvm/ADT/iterator.h"
|
|
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
|
|
#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
|
|
#include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
|
|
#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
|
|
#include "llvm/Object/Binary.h"
|
|
#include "llvm/Object/ObjectFile.h"
|
|
#include "llvm/Support/Error.h"
|
|
|
|
namespace llvm {
|
|
namespace codeview {
|
|
class LazyRandomTypeCollection;
|
|
}
|
|
namespace object {
|
|
class COFFObjectFile;
|
|
} // namespace object
|
|
|
|
namespace pdb {
|
|
class InputFile;
|
|
class LinePrinter;
|
|
class PDBFile;
|
|
class NativeSession;
|
|
class SymbolGroupIterator;
|
|
class SymbolGroup;
|
|
|
|
class InputFile {
|
|
InputFile();
|
|
|
|
std::unique_ptr<NativeSession> PdbSession;
|
|
object::OwningBinary<object::Binary> CoffObject;
|
|
std::unique_ptr<MemoryBuffer> UnknownFile;
|
|
PointerUnion<PDBFile *, object::COFFObjectFile *, MemoryBuffer *> PdbOrObj;
|
|
|
|
using TypeCollectionPtr = std::unique_ptr<codeview::LazyRandomTypeCollection>;
|
|
|
|
TypeCollectionPtr Types;
|
|
TypeCollectionPtr Ids;
|
|
|
|
enum TypeCollectionKind { kTypes, kIds };
|
|
codeview::LazyRandomTypeCollection &
|
|
getOrCreateTypeCollection(TypeCollectionKind Kind);
|
|
|
|
public:
|
|
InputFile(PDBFile *Pdb) { PdbOrObj = Pdb; }
|
|
InputFile(object::COFFObjectFile *Obj) { PdbOrObj = Obj; }
|
|
InputFile(MemoryBuffer *Buffer) { PdbOrObj = Buffer; }
|
|
~InputFile();
|
|
InputFile(InputFile &&Other) = default;
|
|
|
|
static Expected<InputFile> open(StringRef Path,
|
|
bool AllowUnknownFile = false);
|
|
|
|
PDBFile &pdb();
|
|
const PDBFile &pdb() const;
|
|
object::COFFObjectFile &obj();
|
|
const object::COFFObjectFile &obj() const;
|
|
MemoryBuffer &unknown();
|
|
const MemoryBuffer &unknown() const;
|
|
|
|
StringRef getFilePath() const;
|
|
|
|
bool hasTypes() const;
|
|
bool hasIds() const;
|
|
|
|
codeview::LazyRandomTypeCollection &types();
|
|
codeview::LazyRandomTypeCollection &ids();
|
|
|
|
iterator_range<SymbolGroupIterator> symbol_groups();
|
|
SymbolGroupIterator symbol_groups_begin();
|
|
SymbolGroupIterator symbol_groups_end();
|
|
|
|
bool isPdb() const;
|
|
bool isObj() const;
|
|
bool isUnknown() const;
|
|
};
|
|
|
|
class SymbolGroup {
|
|
friend class SymbolGroupIterator;
|
|
|
|
public:
|
|
explicit SymbolGroup(InputFile *File, uint32_t GroupIndex = 0);
|
|
|
|
Expected<StringRef> getNameFromStringTable(uint32_t Offset) const;
|
|
Expected<StringRef> getNameFromChecksums(uint32_t Offset) const;
|
|
|
|
void formatFromFileName(LinePrinter &Printer, StringRef File,
|
|
bool Append = false) const;
|
|
|
|
void formatFromChecksumsOffset(LinePrinter &Printer, uint32_t Offset,
|
|
bool Append = false) const;
|
|
|
|
StringRef name() const;
|
|
|
|
codeview::DebugSubsectionArray getDebugSubsections() const {
|
|
return Subsections;
|
|
}
|
|
const ModuleDebugStreamRef &getPdbModuleStream() const;
|
|
|
|
const InputFile &getFile() const { return *File; }
|
|
InputFile &getFile() { return *File; }
|
|
|
|
bool hasDebugStream() const { return DebugStream != nullptr; }
|
|
|
|
private:
|
|
void initializeForPdb(uint32_t Modi);
|
|
void updatePdbModi(uint32_t Modi);
|
|
void updateDebugS(const codeview::DebugSubsectionArray &SS);
|
|
|
|
void rebuildChecksumMap();
|
|
InputFile *File = nullptr;
|
|
StringRef Name;
|
|
codeview::DebugSubsectionArray Subsections;
|
|
std::shared_ptr<ModuleDebugStreamRef> DebugStream;
|
|
codeview::StringsAndChecksumsRef SC;
|
|
StringMap<codeview::FileChecksumEntry> ChecksumsByFile;
|
|
};
|
|
|
|
class SymbolGroupIterator
|
|
: public iterator_facade_base<SymbolGroupIterator,
|
|
std::forward_iterator_tag, SymbolGroup> {
|
|
public:
|
|
SymbolGroupIterator();
|
|
explicit SymbolGroupIterator(InputFile &File);
|
|
SymbolGroupIterator(const SymbolGroupIterator &Other) = default;
|
|
SymbolGroupIterator &operator=(const SymbolGroupIterator &R) = default;
|
|
|
|
const SymbolGroup &operator*() const;
|
|
SymbolGroup &operator*();
|
|
|
|
bool operator==(const SymbolGroupIterator &R) const;
|
|
SymbolGroupIterator &operator++();
|
|
|
|
private:
|
|
void scanToNextDebugS();
|
|
bool isEnd() const;
|
|
|
|
uint32_t Index = 0;
|
|
std::optional<object::section_iterator> SectionIter;
|
|
SymbolGroup Value;
|
|
};
|
|
|
|
Expected<ModuleDebugStreamRef>
|
|
getModuleDebugStream(PDBFile &File, StringRef &ModuleName, uint32_t Index);
|
|
Expected<ModuleDebugStreamRef> getModuleDebugStream(PDBFile &File,
|
|
uint32_t Index);
|
|
|
|
bool shouldDumpSymbolGroup(uint32_t Idx, const SymbolGroup &Group,
|
|
const FilterOptions &Filters);
|
|
|
|
// TODO: Change these callbacks to be function_refs (de-templatify them).
|
|
template <typename CallbackT>
|
|
Error iterateOneModule(InputFile &File, const PrintScope &HeaderScope,
|
|
const SymbolGroup &SG, uint32_t Modi,
|
|
CallbackT Callback) {
|
|
HeaderScope.P.formatLine(
|
|
"Mod {0:4} | `{1}`: ",
|
|
fmt_align(Modi, AlignStyle::Right, HeaderScope.LabelWidth), SG.name());
|
|
|
|
AutoIndent Indent(HeaderScope);
|
|
return Callback(Modi, SG);
|
|
}
|
|
|
|
template <typename CallbackT>
|
|
Error iterateSymbolGroups(InputFile &Input, const PrintScope &HeaderScope,
|
|
CallbackT Callback) {
|
|
AutoIndent Indent(HeaderScope);
|
|
|
|
FilterOptions Filters = HeaderScope.P.getFilters();
|
|
if (Filters.DumpModi) {
|
|
uint32_t Modi = *Filters.DumpModi;
|
|
SymbolGroup SG(&Input, Modi);
|
|
return iterateOneModule(Input, withLabelWidth(HeaderScope, NumDigits(Modi)),
|
|
SG, Modi, Callback);
|
|
}
|
|
|
|
uint32_t I = 0;
|
|
|
|
for (const auto &SG : Input.symbol_groups()) {
|
|
if (shouldDumpSymbolGroup(I, SG, Filters))
|
|
if (auto Err =
|
|
iterateOneModule(Input, withLabelWidth(HeaderScope, NumDigits(I)),
|
|
SG, I, Callback))
|
|
return Err;
|
|
|
|
++I;
|
|
}
|
|
return Error::success();
|
|
}
|
|
|
|
template <typename SubsectionT>
|
|
Error iterateModuleSubsections(
|
|
InputFile &File, const PrintScope &HeaderScope,
|
|
llvm::function_ref<Error(uint32_t, const SymbolGroup &, SubsectionT &)>
|
|
Callback) {
|
|
|
|
return iterateSymbolGroups(
|
|
File, HeaderScope, [&](uint32_t Modi, const SymbolGroup &SG) -> Error {
|
|
for (const auto &SS : SG.getDebugSubsections()) {
|
|
SubsectionT Subsection;
|
|
|
|
if (SS.kind() != Subsection.kind())
|
|
continue;
|
|
|
|
BinaryStreamReader Reader(SS.getRecordData());
|
|
if (auto Err = Subsection.initialize(Reader))
|
|
continue;
|
|
if (auto Err = Callback(Modi, SG, Subsection))
|
|
return Err;
|
|
}
|
|
return Error::success();
|
|
});
|
|
}
|
|
|
|
} // namespace pdb
|
|
} // namespace llvm
|
|
|
|
#endif
|