43#define DEBUG_TYPE "CodeViewReader"
47#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
50#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
59#define RETURN_CASE(Enum, X, Ret) \
63 if (CPU == CPUType::ARMNT) {
65#define CV_REGISTERS_ARM
66#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
67#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
69#undef CV_REGISTERS_ARM
74 }
else if (CPU == CPUType::ARM64) {
76#define CV_REGISTERS_ARM64
77#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
78#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
80#undef CV_REGISTERS_ARM64
87#define CV_REGISTERS_X86
88#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
89#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
91#undef CV_REGISTERS_X86
97 return "formatUnknownEnum(Id)";
106 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
107 if (!resolveSymbolName(CoffSection, RelocOffset, Symbol))
117 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
118 if (resolveSymbolName(CoffSection, RelocOffset, Symbol))
123LVCodeViewReader::getFileNameForFileOffset(
uint32_t FileOffset,
135 if (!CVFileChecksumTable.
valid() || !CVStringTable.
valid())
139 CVFileChecksumTable.
getArray().
at(FileOffset);
142 if (Iter == CVFileChecksumTable.
end())
161void LVCodeViewReader::cacheRelocations() {
166 RelocMap[CoffSection].push_back(Relocacion);
170 return L.getOffset() <
R.getOffset();
179 const auto &Relocations =
RelocMap[CoffSection];
182 uint64_t RelocationOffset = Relocation.getOffset();
184 if (RelocationOffset ==
Offset) {
185 SymI = Relocation.getSymbol();
189 if (SymI == getObj().symbol_end())
200 if (
Error E = resolveSymbol(CoffSection,
Offset, Symbol))
216 auto Starts = [=](
const char *
Pattern) ->
bool {
219 auto CheckExclude = [&]() ->
bool {
220 if (Starts(
"__") || Starts(
"_PMD") || Starts(
"_PMFN"))
224 if (
Find(
"_CatchableType") ||
Find(
"_TypeDescriptor"))
226 if (
Find(
"Intermediate\\vctools"))
228 if (
Find(
"$initializer$") ||
Find(
"dynamic initializer"))
230 if (
Find(
"`vftable'") ||
Find(
"_GLOBAL__sub"))
234 bool Excluded = CheckExclude();
236 Element->setIsSystem();
241Error LVCodeViewReader::collectInlineeInfo(
250 if (
Error Err = printFileNameForOffset(
"FileID", FileOffset, SG))
254 if (
Lines.hasExtraFiles()) {
257 for (
const ulittle32_t &FID :
Line.ExtraFiles)
258 if (
Error Err = printFileNameForOffset(
"FileID", FID, SG))
264 return NameOrErr.takeError();
271Error LVCodeViewReader::traverseInlineeLines(
StringRef Subsection) {
277 return collectInlineeInfo(Lines);
280Error LVCodeViewReader::createLines(
297 "{0} {1:x-8}\n", utostr(LI.getStartLine()),
307 LineDebug->setAddress(
Address + Addendum);
309 if (LI.isAlwaysStepInto())
310 LineDebug->setIsAlwaysStepInto();
311 else if (LI.isNeverStepInto())
312 LineDebug->setIsNeverStepInto();
314 LineDebug->setLineNumber(LI.getStartLine());
316 if (LI.isStatement())
317 LineDebug->setIsNewStatement();
322 LineDebug->setFilename(*NameOrErr);
328Error LVCodeViewReader::initializeFileAndStringTables(
331 (!CVFileChecksumTable.
valid() || !CVStringTable.
valid())) {
347 case DebugSubsectionKind::FileChecksums:
351 case DebugSubsectionKind::StringTable:
360 if (
Error E = Reader.
skip(PaddedSize - SubSectionSize))
376 if (BuffOrErr.getError()) {
381 if (BuffOrErr.getError()) {
384 "File '%s' does not exist.",
388 MemBuffer = std::move(BuffOrErr.get());
392 "Invalid PDB file.");
398 PdbSession.reset(
static_cast<NativeSession *
>(Session.release()));
405 if (!expectedInfo || expectedInfo->getGuid() != TS.
getGuid())
411 TypeServer = std::make_shared<InputFile>(&
Pdb);
412 LogicalVisitor.
setInput(TypeServer);
416 if (
Error Err = traverseTypes(
Pdb, Types, Ids))
432 if (BuffOrErr.getError()) {
435 if (BuffOrErr.getError()) {
438 "File '%s' does not exist.",
442 MemBuffer = std::move(BuffOrErr.get());
447 "Binary object format in '%s' is not supported.",
455 Builder = std::make_unique<AppendingTypeTableBuilder>(BuilderAllocator);
462 if (!SectionNameOrErr)
464 if (*SectionNameOrErr ==
".debug$P") {
474 ReaderPrecomp = std::make_unique<BinaryStreamReader>(
477 ReaderPrecomp->readArray(CVTypesPrecomp, ReaderPrecomp->getLength()));
483 if (
Type.kind() == LF_ENDPRECOMP) {
485 TypeDeserializer::deserializeAs<EndPrecompRecord>(TypeData));
490 Builder->insertRecordBytes(TypeData);
501 if (
Type.kind() != LF_PRECOMP)
502 Builder->insertRecordBytes(TypeData);
506 Builder->ForEachRecord(
511 ItemStream->setItems(TypeArray);
515 std::make_shared<LazyRandomTypeCollection>(TypeStream, TypeArray.size());
518 LogicalVisitor.
setInput(PrecompHeader);
536 return DataOrErr.takeError();
551 if (FirstType->kind() == LF_TYPESERVER2) {
553 TypeDeserializer::deserializeAs<TypeServer2Record>(FirstType->data()));
554 return loadTypeServer(TS);
559 if (FirstType->kind() == LF_PRECOMP) {
561 TypeDeserializer::deserializeAs<PrecompRecord>(FirstType->data()));
562 return loadPrecompiledObject(Precomp, CVTypes);
567 Types.reset(*DataOrErr, 100);
609Error LVCodeViewReader::traverseSymbolsSubsection(
StringRef Subsection,
625 CodeViewContainer::ObjectFile);
629 &VisitorDelegate, LogicalVisitor.
getShared());
634 return Visitor.visitSymbolStream(Symbols);
646 return SectionOrErr.takeError();
647 StringRef SectionContents = *SectionOrErr;
661 if (
Error Err = initializeFileAndStringTables(FSReader))
664 while (!
Data.empty()) {
674 SubType &= ~SubsectionIgnoreFlag;
677 if (SubSectionSize >
Data.size())
685 NextOffset =
alignTo(NextOffset, 4);
686 if (NextOffset > SectionContents.
size())
691 case DebugSubsectionKind::Symbols:
693 traverseSymbolsSubsection(Contents, Section, SectionContents))
697 case DebugSubsectionKind::InlineeLines:
698 if (
Error Err = traverseInlineeLines(Contents))
702 case DebugSubsectionKind::Lines:
708 if (
options().getGeneralCollectRanges()) {
710 if (SubSectionSize < 12) {
717 if (
Error Err = resolveSymbolName(getObj().getCOFFSection(Section),
723 if (FunctionLineTables.
count(SymbolName) != 0) {
742 for (
StringRef SymbolName : SymbolNames) {
770 ScopesWithRanges->
clear();
771 Function->getRanges(*ScopesWithRanges);
772 ScopesWithRanges->
sort();
778 if (
Error Err = createLines(
Block.LineNumbers, Addendum, Segment, Begin,
800void LVCodeViewReader::mapRangeAddress(
const ObjectFile &Obj,
809 if (!Section.containsSymbol(
Sym))
819 W.
startLine() <<
"Invalid symbol name: " << Symbol.getSectionNumber()
824 SymbolName = *SymNameOrErr;
828 Object->getSection(Symbol.getSectionNumber());
830 W.
startLine() <<
"Invalid section number: " << Symbol.getSectionNumber()
847 if (
Error Err = loadTargetInfo(Obj))
859 if (!SectionNameOrErr)
863 if (*SectionNameOrErr ==
".debug$T" || *SectionNameOrErr ==
".debug$P")
864 if (
Error Err = traverseTypeSection(*SectionNameOrErr, Section))
873 if (!SectionNameOrErr)
875 if (*SectionNameOrErr ==
".debug$S")
876 if (
Error Err = traverseSymbolSection(*SectionNameOrErr, Section))
895 if (
Error Err = loadTargetInfo(
Pdb))
898 if (!
Pdb.hasPDBTpiStream() || !
Pdb.hasPDBDbiStream())
903 if (!ExePath.empty()) {
908 "File '%s' does not exist.", ExePath.c_str());
910 BinaryBuffer = std::move(BuffOrErr.
get());
915 "Invalid PECOFF executable file.");
921 "Binary object format in '%s' is not supported.",
924 BinaryExecutable = std::move(*BinOrErr);
926 dyn_cast<COFFObjectFile>(BinaryExecutable.get()))
949 if (
Error Err = traverseTypes(
Pdb, Types, Ids))
957 auto VisitInlineeLines = [&](int32_t Modi,
const SymbolGroup &SG,
959 return collectInlineeInfo(Lines, &SG);
965 if (
Error Err = iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
966 Input, HeaderScope, VisitInlineeLines))
971 if (
Pdb.hasPDBGlobalsStream()) {
990 if (
Error Err = Traverser.visitSymbolBegin(Symbol,
Offset))
1004 ExpectedSyms->getSymbolArray().getUnderlyingStream();
1008 if (
Error Err = Visitor.visitSymbolRecord(*
Sym, PubSymOff))
1041 Pipeline.addCallbackToPipeline(Deserializer);
1042 Pipeline.addCallbackToPipeline(Traverser);
1070 auto VisitDebugLines = [
this](int32_t Modi,
const SymbolGroup &SG,
1072 if (!
options().getPrintLines())
1084 if (CurrentModule != Modi) {
1085 if (
Error Err = processModule())
1088 CurrentModule = Modi;
1092 if (
Error Err = createLines(
Block.LineNumbers, 0, Segment,
1099 if (
Error Err = iterateModuleSubsections<DebugLinesSubsectionRef>(
1100 Input, HeaderScope, VisitDebugLines))
1114Error LVCodeViewReader::processModule() {
1128 ScopesWithRanges->
clear();
1130 if (!ScopesWithRanges->
empty())
1133 ScopesWithRanges->
sort();
1193 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...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
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.