48#define DEBUG_TYPE "CodeViewReader"
52#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
55#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
64#define RETURN_CASE(Enum, X, Ret) \
68 if (CPU == CPUType::ARMNT) {
70#define CV_REGISTERS_ARM
71#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
72#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
74#undef CV_REGISTERS_ARM
79 }
else if (CPU == CPUType::ARM64) {
81#define CV_REGISTERS_ARM64
82#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
83#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
85#undef CV_REGISTERS_ARM64
92#define CV_REGISTERS_X86
93#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
94#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
96#undef CV_REGISTERS_X86
102 return "formatUnknownEnum(Id)";
111 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
112 if (!resolveSymbolName(CoffSection, RelocOffset, Symbol))
122 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
123 if (resolveSymbolName(CoffSection, RelocOffset, Symbol))
128LVCodeViewReader::getFileNameForFileOffset(
uint32_t FileOffset,
140 if (!CVFileChecksumTable.
valid() || !CVStringTable.
valid())
144 CVFileChecksumTable.
getArray().
at(FileOffset);
147 if (Iter == CVFileChecksumTable.
end())
166void LVCodeViewReader::cacheRelocations() {
171 RelocMap[CoffSection].push_back(Relocacion);
175 return L.getOffset() <
R.getOffset();
184 const auto &Relocations =
RelocMap[CoffSection];
187 uint64_t RelocationOffset = Relocation.getOffset();
189 if (RelocationOffset ==
Offset) {
190 SymI = Relocation.getSymbol();
194 if (SymI == getObj().symbol_end())
205 if (
Error E = resolveSymbol(CoffSection,
Offset, Symbol))
221 auto Starts = [=](
const char *
Pattern) ->
bool {
224 auto CheckExclude = [&]() ->
bool {
225 if (Starts(
"__") || Starts(
"_PMD") || Starts(
"_PMFN"))
229 if (
Find(
"_CatchableType") ||
Find(
"_TypeDescriptor"))
231 if (
Find(
"Intermediate\\vctools"))
233 if (
Find(
"$initializer$") ||
Find(
"dynamic initializer"))
235 if (
Find(
"`vftable'") ||
Find(
"_GLOBAL__sub"))
239 bool Excluded = CheckExclude();
241 Element->setIsSystem();
246Error LVCodeViewReader::collectInlineeInfo(
255 if (
Error Err = printFileNameForOffset(
"FileID", FileOffset, SG))
259 if (
Lines.hasExtraFiles()) {
262 for (
const ulittle32_t &FID :
Line.ExtraFiles)
263 if (
Error Err = printFileNameForOffset(
"FileID", FID, SG))
269 return NameOrErr.takeError();
276Error LVCodeViewReader::traverseInlineeLines(
StringRef Subsection) {
282 return collectInlineeInfo(Lines);
285Error LVCodeViewReader::createLines(
302 "{0} {1:x-8}\n", utostr(LI.getStartLine()),
312 LineDebug->setAddress(
Address + Addendum);
314 if (LI.isAlwaysStepInto())
315 LineDebug->setIsAlwaysStepInto();
316 else if (LI.isNeverStepInto())
317 LineDebug->setIsNeverStepInto();
319 LineDebug->setLineNumber(LI.getStartLine());
321 if (LI.isStatement())
322 LineDebug->setIsNewStatement();
327 LineDebug->setFilename(*NameOrErr);
333Error LVCodeViewReader::initializeFileAndStringTables(
336 (!CVFileChecksumTable.
valid() || !CVStringTable.
valid())) {
352 case DebugSubsectionKind::FileChecksums:
356 case DebugSubsectionKind::StringTable:
365 if (
Error E = Reader.
skip(PaddedSize - SubSectionSize))
381 if (BuffOrErr.getError()) {
386 if (BuffOrErr.getError()) {
389 "File '%s' does not exist.",
393 MemBuffer = std::move(BuffOrErr.get());
397 "Invalid PDB file.");
403 PdbSession.reset(
static_cast<NativeSession *
>(Session.release()));
410 if (!expectedInfo || expectedInfo->getGuid() != TS.
getGuid())
416 TypeServer = std::make_shared<InputFile>(&
Pdb);
417 LogicalVisitor.
setInput(TypeServer);
421 if (
Error Err = traverseTypes(
Pdb, Types, Ids))
437 if (BuffOrErr.getError()) {
440 if (BuffOrErr.getError()) {
443 "File '%s' does not exist.",
447 MemBuffer = std::move(BuffOrErr.get());
452 "Binary object format in '%s' is not supported.",
460 Builder = std::make_unique<AppendingTypeTableBuilder>(BuilderAllocator);
467 if (!SectionNameOrErr)
469 if (*SectionNameOrErr ==
".debug$P") {
479 ReaderPrecomp = std::make_unique<BinaryStreamReader>(
482 ReaderPrecomp->readArray(CVTypesPrecomp, ReaderPrecomp->getLength()));
488 if (
Type.kind() == LF_ENDPRECOMP) {
490 TypeDeserializer::deserializeAs<EndPrecompRecord>(TypeData));
495 Builder->insertRecordBytes(TypeData);
506 if (
Type.kind() != LF_PRECOMP)
507 Builder->insertRecordBytes(TypeData);
511 Builder->ForEachRecord(
516 ItemStream->setItems(TypeArray);
520 std::make_shared<LazyRandomTypeCollection>(TypeStream, TypeArray.size());
523 LogicalVisitor.
setInput(PrecompHeader);
541 return DataOrErr.takeError();
556 if (FirstType->kind() == LF_TYPESERVER2) {
558 TypeDeserializer::deserializeAs<TypeServer2Record>(FirstType->data()));
559 return loadTypeServer(TS);
564 if (FirstType->kind() == LF_PRECOMP) {
566 TypeDeserializer::deserializeAs<PrecompRecord>(FirstType->data()));
567 return loadPrecompiledObject(Precomp, CVTypes);
572 Types.reset(*DataOrErr, 100);
614Error LVCodeViewReader::traverseSymbolsSubsection(
StringRef Subsection,
630 CodeViewContainer::ObjectFile);
634 &VisitorDelegate, LogicalVisitor.
getShared());
639 return Visitor.visitSymbolStream(Symbols);
651 return SectionOrErr.takeError();
652 StringRef SectionContents = *SectionOrErr;
666 if (
Error Err = initializeFileAndStringTables(FSReader))
669 while (!
Data.empty()) {
679 SubType &= ~SubsectionIgnoreFlag;
682 if (SubSectionSize >
Data.size())
690 NextOffset =
alignTo(NextOffset, 4);
691 if (NextOffset > SectionContents.
size())
696 case DebugSubsectionKind::Symbols:
698 traverseSymbolsSubsection(Contents, Section, SectionContents))
702 case DebugSubsectionKind::InlineeLines:
703 if (
Error Err = traverseInlineeLines(Contents))
707 case DebugSubsectionKind::Lines:
713 if (
options().getGeneralCollectRanges()) {
715 if (SubSectionSize < 12) {
722 if (
Error Err = resolveSymbolName(getObj().getCOFFSection(Section),
728 if (FunctionLineTables.
count(SymbolName) != 0) {
747 for (
StringRef SymbolName : SymbolNames) {
775 ScopesWithRanges->
clear();
776 Function->getRanges(*ScopesWithRanges);
777 ScopesWithRanges->
sort();
783 if (
Error Err = createLines(
Block.LineNumbers, Addendum, Segment, Begin,
805void LVCodeViewReader::mapRangeAddress(
const ObjectFile &Obj,
814 if (!Section.containsSymbol(
Sym))
824 W.
startLine() <<
"Invalid symbol name: " << Symbol.getSectionNumber()
829 SymbolName = *SymNameOrErr;
833 Object->getSection(Symbol.getSectionNumber());
835 W.
startLine() <<
"Invalid section number: " << Symbol.getSectionNumber()
852 if (
Error Err = loadTargetInfo(Obj))
864 if (!SectionNameOrErr)
868 if (*SectionNameOrErr ==
".debug$T" || *SectionNameOrErr ==
".debug$P")
869 if (
Error Err = traverseTypeSection(*SectionNameOrErr, Section))
878 if (!SectionNameOrErr)
880 if (*SectionNameOrErr ==
".debug$S")
881 if (
Error Err = traverseSymbolSection(*SectionNameOrErr, Section))
900 if (
Error Err = loadTargetInfo(
Pdb))
903 if (!
Pdb.hasPDBTpiStream() || !
Pdb.hasPDBDbiStream())
908 if (!ExePath.empty()) {
913 "File '%s' does not exist.", ExePath.c_str());
915 BinaryBuffer = std::move(BuffOrErr.
get());
920 "Invalid PECOFF executable file.");
926 "Binary object format in '%s' is not supported.",
929 BinaryExecutable = std::move(*BinOrErr);
931 dyn_cast<COFFObjectFile>(BinaryExecutable.get()))
954 if (
Error Err = traverseTypes(
Pdb, Types, Ids))
962 auto VisitInlineeLines = [&](int32_t Modi,
const SymbolGroup &SG,
964 return collectInlineeInfo(Lines, &SG);
970 if (
Error Err = iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
971 Input, HeaderScope, VisitInlineeLines))
976 if (
Pdb.hasPDBGlobalsStream()) {
995 if (
Error Err = Traverser.visitSymbolBegin(Symbol,
Offset))
1009 ExpectedSyms->getSymbolArray().getUnderlyingStream();
1013 if (
Error Err = Visitor.visitSymbolRecord(*
Sym, PubSymOff))
1046 Pipeline.addCallbackToPipeline(Deserializer);
1047 Pipeline.addCallbackToPipeline(Traverser);
1075 auto VisitDebugLines = [
this](int32_t Modi,
const SymbolGroup &SG,
1077 if (!
options().getPrintLines())
1089 if (CurrentModule != Modi) {
1090 if (
Error Err = processModule())
1093 CurrentModule = Modi;
1097 if (
Error Err = createLines(
Block.LineNumbers, 0, Segment,
1104 if (
Error Err = iterateModuleSubsections<DebugLinesSubsectionRef>(
1105 Input, HeaderScope, VisitDebugLines))
1119Error LVCodeViewReader::processModule() {
1133 ScopesWithRanges->
clear();
1135 if (!ScopesWithRanges->
empty())
1138 ScopesWithRanges->
sort();
1198 FeaturesValue = *Features;
bbsections Prepares for basic block sections
dxil pretty DXIL Metadata Pretty Printer
static const T * Find(StringRef S, ArrayRef< T > A)
Find KV in array using binary search.
mir Rename Register Operands
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getSectionID(const ObjectFile &O, SectionRef Sec)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Provides read only access to a subclass of BinaryStream.
uint64_t getLength() const
Error readInteger(T &Dest)
Read an integer of the specified endianness into Dest and update the stream's offset.
uint64_t bytesRemaining() const
Error readFixedString(StringRef &Dest, uint32_t Length)
Read a Length byte string into Dest.
Error readArray(ArrayRef< T > &Array, uint32_t NumElements)
Get a reference to a NumElements element array of objects of type T from the underlying stream as if ...
Error skip(uint64_t Amount)
Advance the stream's offset by Amount bytes.
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
Represents either an error or a value T.
std::error_code getError() const
Subclass of Error for the sole purpose of identifying the success path in the type system.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
FixedStreamArray is similar to VarStreamArray, except with each record having a fixed-length.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
Wrapper class representing virtual and physical registers.
virtual void printString(StringRef Value)
virtual raw_ostream & getOStream()
virtual raw_ostream & startLine()
virtual void printNumber(StringRef Label, char Value)
void printHex(StringRef Label, T Value)
void printSymbolOffset(StringRef Label, StringRef Symbol, T Value)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
const unsigned char * bytes_end() const
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
const unsigned char * bytes_begin() const
Manages the enabling and disabling of subtarget specific features.
std::string getString() const
Returns features as a string.
Symbol info for RuntimeDyld.
Triple - Helper class for working with autoconf configuration names.
The instances of the Type class are immutable: once they are created, they are never changed.
VarStreamArray represents an array of variable length records backed by a stream.
void setUnderlyingStream(BinaryStreamRef NewStream, uint32_t NewSkew=0)
Iterator at(uint32_t Offset) const
given an offset into the array's underlying stream, return an iterator to the record at that offset.
Iterator begin(bool *HadError=nullptr) const
Error initialize(BinaryStreamReader Reader)
const FileChecksumArray & getArray() const
Expected< StringRef > getString(uint32_t Offset) const
Error initialize(BinaryStreamRef Contents)
uint32_t getSignature() const
Provides amortized O(1) random access to a CodeView type stream.
uint32_t getSignature() const
StringRef getPrecompFilePath() const
uint32_t getTypesCount() const
void addCallbackToPipeline(SymbolVisitorCallbacks &Callbacks)
StringRef getName() const
const GUID & getGuid() const
Stores all information relating to a compile unit, be it in its original instance in the object file ...
const LVSymbolTableEntry & getSymbolTableEntry(StringRef Name)
void includeInlineeLines(LVSectionIndex SectionIndex, LVScope *Function)
LVAddress linearAddress(uint16_t Segment, uint32_t Offset, LVAddress Addendum=0)
void addToSymbolTable(StringRef Name, LVScope *Function, LVSectionIndex SectionIndex=0)
void processLines(LVLines *DebugLines, LVSectionIndex SectionIndex)
void mapVirtualAddress(const object::ObjectFile &Obj)
LVRange * getSectionRanges(LVSectionIndex SectionIndex)
Error loadGenericTargetInfo(StringRef TheTriple, StringRef TheFeatures)
Error createInstructions()
void getLinkageName(const llvm::object::coff_section *CoffSection, uint32_t RelocOffset, uint32_t Offset, StringRef *RelocSym)
void print(raw_ostream &OS) const
static std::string formatRegisterId(RegisterId Register, CPUType CPU)
std::string getRegisterName(LVSmall Opcode, ArrayRef< uint64_t > Operands) override
LVScope * getScopeForModule(uint32_t Modi)
Error createScopes() override
static StringRef getSymbolKindName(SymbolKind Kind)
bool isSystemEntry(LVElement *Element, StringRef Name) const override
void sortScopes() override
StringRef getName() const override
void addInlineeInfo(TypeIndex TI, uint32_t LineNumber, StringRef Filename)
void printTypeIndex(StringRef FieldName, TypeIndex TI, uint32_t StreamIdx)
void setRoot(LVScope *Root)
void setInput(std::shared_ptr< llvm::pdb::InputFile > TypeServer)
LVAddress getLower() const
LVAddress getUpper() const
std::string FileFormatName
codeview::CPUType getCompileUnitCPUType()
std::string createAlternativePath(StringRef From)
LVSectionIndex DotTextSectionIndex
virtual Error createScopes()
void transformScopedName()
basic_symbol_iterator symbol_end() const override
const coff_section * getCOFFSection(const SectionRef &Section) const
This class is the base class for all object file types.
virtual Expected< SubtargetFeatures > getFeatures() const =0
section_iterator_range sections() const
virtual Triple::ArchType getArch() const =0
This is a value type class that represents a single relocation in the list of relocations in the obje...
This is a value type class that represents a single section in the list of sections in the object fil...
This is a value type class that represents a single symbol in the list of symbols in the object file.
A readonly view of a hash table used in the globals and publics streams.
const GSIHashTable & getGlobalsTable() const
BinarySubstreamRef getSymbolsSubstream() const
const codeview::CVSymbolArray & getSymbolArray() const
Expected< StringRef > getNameFromChecksums(uint32_t Offset) const
uint32_t getNumTypeRecords() const
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
@ IMAGE_SYM_DTYPE_FUNCTION
A function that returns a base type.
CPUType
These values correspond to the CV_CPU_TYPE_e enumeration, and are documented here: https://msdn....
Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
SymbolKind
Duplicate copy of the above enum, but using the official CV names.
@ D
The DMD compiler emits 'D' for the CV source language.
Expected< CVSymbol > readSymbolFromStream(BinaryStreamRef Stream, uint32_t Offset)
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
static const char Magic[]
Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)
Create a Binary from Source, autodetecting the file type.
Expected< ModuleDebugStreamRef > getModuleDebugStream(PDBFile &File, StringRef &ModuleName, uint32_t Index)
Error loadDataForPDB(PDB_ReaderType Type, StringRef Path, std::unique_ptr< IPDBSession > &Session)
Error iterateSymbolGroups(InputFile &Input, const PrintScope &HeaderScope, CallbackT Callback)
This is an optimization pass for GlobalISel generic memory operations.
file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
raw_ostream & nulls()
This returns a reference to a raw_ostream which simply discards output.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
support::detail::AlignAdapter< T > fmt_align(T &&Item, AlignStyle Where, size_t Amount, char Fill=' ')
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
void consumeError(Error Err)
Consume a Error without doing anything.
@ pdb
Windows PDB debug info file.
@ pecoff_executable
PECOFF executable file.