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() {
167 for (
const SectionRef &Section : getObj().sections()) {
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))
223 auto Starts = [=](
const char *
Pattern) ->
bool {
226 auto CheckExclude = [&]() ->
bool {
227 if (Starts(
"__") || Starts(
"_PMD") || Starts(
"_PMFN"))
231 if (
Find(
"_CatchableType") ||
Find(
"_TypeDescriptor"))
233 if (
Find(
"Intermediate\\vctools"))
235 if (
Find(
"$initializer$") ||
Find(
"dynamic initializer"))
237 if (
Find(
"`vftable'") ||
Find(
"_GLOBAL__sub"))
241 bool Excluded = CheckExclude();
243 Element->setIsSystem();
248Error LVCodeViewReader::collectInlineeInfo(
257 if (
Error Err = printFileNameForOffset(
"FileID", FileOffset, SG))
261 if (
Lines.hasExtraFiles()) {
264 for (
const ulittle32_t &FID :
Line.ExtraFiles)
265 if (
Error Err = printFileNameForOffset(
"FileID", FID, SG))
271 return NameOrErr.takeError();
278Error LVCodeViewReader::traverseInlineeLines(
StringRef Subsection) {
284 return collectInlineeInfo(Lines);
287Error LVCodeViewReader::createLines(
304 "{0} {1:x-8}\n", utostr(LI.getStartLine()),
314 LineDebug->setAddress(
Address + Addendum);
316 if (LI.isAlwaysStepInto())
317 LineDebug->setIsAlwaysStepInto();
318 else if (LI.isNeverStepInto())
319 LineDebug->setIsNeverStepInto();
321 LineDebug->setLineNumber(LI.getStartLine());
323 if (LI.isStatement())
324 LineDebug->setIsNewStatement();
329 LineDebug->setFilename(*NameOrErr);
335Error LVCodeViewReader::initializeFileAndStringTables(
338 (!CVFileChecksumTable.
valid() || !CVStringTable.
valid())) {
354 case DebugSubsectionKind::FileChecksums:
358 case DebugSubsectionKind::StringTable:
367 if (
Error E = Reader.
skip(PaddedSize - SubSectionSize))
383 if (BuffOrErr.getError()) {
388 if (BuffOrErr.getError()) {
391 "File '%s' does not exist.",
395 MemBuffer = std::move(BuffOrErr.get());
399 "Invalid PDB file.");
405 PdbSession.reset(
static_cast<NativeSession *
>(Session.release()));
412 if (!expectedInfo || expectedInfo->getGuid() != TS.
getGuid())
418 TypeServer = std::make_shared<InputFile>(&
Pdb);
419 LogicalVisitor.
setInput(TypeServer);
423 if (
Error Err = traverseTypes(
Pdb, Types, Ids))
439 if (BuffOrErr.getError()) {
442 if (BuffOrErr.getError()) {
445 "File '%s' does not exist.",
449 MemBuffer = std::move(BuffOrErr.get());
454 "Binary object format in '%s' is not supported.",
462 Builder = std::make_unique<AppendingTypeTableBuilder>(BuilderAllocator);
469 if (!SectionNameOrErr)
471 if (*SectionNameOrErr ==
".debug$P") {
484 ReaderPrecomp->readArray(CVTypesPrecomp, ReaderPrecomp->getLength()));
490 if (
Type.kind() == LF_ENDPRECOMP) {
492 TypeDeserializer::deserializeAs<EndPrecompRecord>(TypeData));
497 Builder->insertRecordBytes(TypeData);
508 if (
Type.kind() != LF_PRECOMP)
509 Builder->insertRecordBytes(TypeData);
513 Builder->ForEachRecord(
518 ItemStream->setItems(TypeArray);
522 std::make_shared<LazyRandomTypeCollection>(TypeStream, TypeArray.size());
525 LogicalVisitor.
setInput(PrecompHeader);
543 return DataOrErr.takeError();
558 if (FirstType->kind() == LF_TYPESERVER2) {
560 TypeDeserializer::deserializeAs<TypeServer2Record>(FirstType->data()));
561 return loadTypeServer(TS);
566 if (FirstType->kind() == LF_PRECOMP) {
568 TypeDeserializer::deserializeAs<PrecompRecord>(FirstType->data()));
569 return loadPrecompiledObject(Precomp, CVTypes);
574 Types.reset(*DataOrErr, 100);
616Error LVCodeViewReader::traverseSymbolsSubsection(
StringRef Subsection,
632 CodeViewContainer::ObjectFile);
636 &VisitorDelegate, LogicalVisitor.
getShared());
641 return Visitor.visitSymbolStream(Symbols);
653 return SectionOrErr.takeError();
654 StringRef SectionContents = *SectionOrErr;
668 if (
Error Err = initializeFileAndStringTables(FSReader))
671 while (!
Data.empty()) {
681 SubType &= ~SubsectionIgnoreFlag;
684 if (SubSectionSize >
Data.size())
692 NextOffset =
alignTo(NextOffset, 4);
693 if (NextOffset > SectionContents.
size())
698 case DebugSubsectionKind::Symbols:
700 traverseSymbolsSubsection(Contents, Section, SectionContents))
704 case DebugSubsectionKind::InlineeLines:
705 if (
Error Err = traverseInlineeLines(Contents))
709 case DebugSubsectionKind::Lines:
715 if (
options().getGeneralCollectRanges()) {
717 if (SubSectionSize < 12) {
724 if (
Error Err = resolveSymbolName(getObj().getCOFFSection(Section),
730 if (FunctionLineTables.
count(SymbolName) != 0) {
749 for (
StringRef SymbolName : SymbolNames) {
776 ScopesWithRanges->
clear();
777 Function->getRanges(*ScopesWithRanges);
778 ScopesWithRanges->
sort();
784 if (
Error Err = createLines(
Block.LineNumbers, Addendum, Segment, Begin,
806void LVCodeViewReader::mapRangeAddress(
const ObjectFile &Obj,
815 if (!Section.containsSymbol(
Sym))
825 W.
startLine() <<
"Invalid symbol name: " << Symbol.getSectionNumber()
830 SymbolName = *SymNameOrErr;
834 Object->getSection(Symbol.getSectionNumber());
836 W.
startLine() <<
"Invalid section number: " << Symbol.getSectionNumber()
853 if (
Error Err = loadTargetInfo(Obj))
865 if (!SectionNameOrErr)
869 if (*SectionNameOrErr ==
".debug$T" || *SectionNameOrErr ==
".debug$P")
870 if (
Error Err = traverseTypeSection(*SectionNameOrErr, Section))
879 if (!SectionNameOrErr)
881 if (*SectionNameOrErr ==
".debug$S")
882 if (
Error Err = traverseSymbolSection(*SectionNameOrErr, Section))
901 if (
Error Err = loadTargetInfo(
Pdb))
904 if (!
Pdb.hasPDBTpiStream() || !
Pdb.hasPDBDbiStream())
909 if (!ExePath.empty()) {
914 "File '%s' does not exist.", ExePath.c_str());
916 BinaryBuffer = std::move(BuffOrErr.
get());
921 "Invalid PECOFF executable file.");
927 "Binary object format in '%s' is not supported.",
930 BinaryExecutable = std::move(*BinOrErr);
932 dyn_cast<COFFObjectFile>(BinaryExecutable.get()))
955 if (
Error Err = traverseTypes(
Pdb, Types, Ids))
963 auto VisitInlineeLines = [&](int32_t Modi,
const SymbolGroup &SG,
965 return collectInlineeInfo(Lines, &SG);
971 if (
Error Err = iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
972 Input, HeaderScope, VisitInlineeLines))
977 if (
Pdb.hasPDBGlobalsStream()) {
996 if (
Error Err = Traverser.visitSymbolBegin(Symbol,
Offset))
1010 ExpectedSyms->getSymbolArray().getUnderlyingStream();
1014 if (
Error Err = Visitor.visitSymbolRecord(*
Sym, PubSymOff))
1047 Pipeline.addCallbackToPipeline(Deserializer);
1048 Pipeline.addCallbackToPipeline(Traverser);
1076 auto VisitDebugLines = [
this](int32_t Modi,
const SymbolGroup &SG,
1078 if (!
options().getPrintLines())
1090 if (CurrentModule != Modi) {
1091 if (
Error Err = processModule())
1094 CurrentModule = Modi;
1098 if (
Error Err = createLines(
Block.LineNumbers, 0, Segment,
1105 if (
Error Err = iterateModuleSubsections<DebugLinesSubsectionRef>(
1106 Input, HeaderScope, VisitDebugLines))
1120Error LVCodeViewReader::processModule() {
1134 ScopesWithRanges->
clear();
1136 if (!ScopesWithRanges->
empty())
1139 ScopesWithRanges->
sort();
1199 FeaturesValue = *Features;
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static const T * Find(StringRef S, ArrayRef< T > A)
Find KV in array using binary search.
mir Rename Register Operands
Memory true print Memory SSA Printer
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.
Stores all information relating to a compile unit, be it in its original instance in the object file ...
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.
static constexpr size_t npos
const unsigned char * bytes_begin() const
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
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
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, uint64_t Operands[2]) 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.
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 & Swift compilers emit 'D' and 'S', respectively, 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.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
detail::AlignAdapter< T > fmt_align(T &&Item, AlignStyle Where, size_t Amount, char Fill=' ')
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.
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.