xref: /freebsd/contrib/llvm-project/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===-- LVCodeViewReader.h --------------------------------------*- C++ -*-===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric //
906c3fb27SDimitry Andric // This file defines the LVCodeViewReader class, which is used to describe a
1006c3fb27SDimitry Andric // debug information (COFF) reader.
1106c3fb27SDimitry Andric //
1206c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
1306c3fb27SDimitry Andric 
1406c3fb27SDimitry Andric #ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H
1506c3fb27SDimitry Andric #define LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H
1606c3fb27SDimitry Andric 
1706c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"
1806c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
1906c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
2006c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
2106c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeRecord.h"
2206c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h"
2306c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h"
2406c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
2506c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/PDB.h"
2606c3fb27SDimitry Andric #include "llvm/Support/BinaryByteStream.h"
2706c3fb27SDimitry Andric #include "llvm/Support/BinaryItemStream.h"
2806c3fb27SDimitry Andric #include "llvm/Support/BinaryStreamArray.h"
2906c3fb27SDimitry Andric 
3006c3fb27SDimitry Andric namespace llvm {
3106c3fb27SDimitry Andric template <> struct BinaryItemTraits<codeview::CVType> {
3206c3fb27SDimitry Andric   static size_t length(const codeview::CVType &Item) { return Item.length(); }
3306c3fb27SDimitry Andric   static ArrayRef<uint8_t> bytes(const codeview::CVType &Item) {
3406c3fb27SDimitry Andric     return Item.data();
3506c3fb27SDimitry Andric   }
3606c3fb27SDimitry Andric };
3706c3fb27SDimitry Andric 
3806c3fb27SDimitry Andric namespace codeview {
3906c3fb27SDimitry Andric class LazyRandomTypeCollection;
4006c3fb27SDimitry Andric }
4106c3fb27SDimitry Andric namespace object {
4206c3fb27SDimitry Andric struct coff_section;
4306c3fb27SDimitry Andric }
4406c3fb27SDimitry Andric namespace pdb {
4506c3fb27SDimitry Andric class SymbolGroup;
4606c3fb27SDimitry Andric }
4706c3fb27SDimitry Andric namespace logicalview {
4806c3fb27SDimitry Andric 
4906c3fb27SDimitry Andric class LVElement;
5006c3fb27SDimitry Andric class LVLine;
5106c3fb27SDimitry Andric class LVScope;
5206c3fb27SDimitry Andric class LVScopeCompileUnit;
5306c3fb27SDimitry Andric class LVSymbol;
5406c3fb27SDimitry Andric class LVType;
5506c3fb27SDimitry Andric class LVTypeVisitor;
5606c3fb27SDimitry Andric class LVSymbolVisitor;
5706c3fb27SDimitry Andric class LVSymbolVisitorDelegate;
5806c3fb27SDimitry Andric 
5906c3fb27SDimitry Andric using LVNames = SmallVector<StringRef, 16>;
6006c3fb27SDimitry Andric 
61*0fca6ea1SDimitry Andric // The DWARF reader uses the DWARF constants to create the logical elements.
6206c3fb27SDimitry Andric // The DW_TAG_* and DW_AT_* are used to select the logical object and to
6306c3fb27SDimitry Andric // set specific attributes, such as name, type, etc.
6406c3fb27SDimitry Andric // As the CodeView constants are different to the DWARF constants, the
6506c3fb27SDimitry Andric // CodeView reader will map them to the DWARF ones.
6606c3fb27SDimitry Andric 
6706c3fb27SDimitry Andric class LVCodeViewReader final : public LVBinaryReader {
6806c3fb27SDimitry Andric   friend class LVTypeVisitor;
6906c3fb27SDimitry Andric   friend class LVSymbolVisitor;
7006c3fb27SDimitry Andric   friend class LVSymbolVisitorDelegate;
7106c3fb27SDimitry Andric 
7206c3fb27SDimitry Andric   using LVModules = std::vector<LVScope *>;
7306c3fb27SDimitry Andric   LVModules Modules;
7406c3fb27SDimitry Andric 
7506c3fb27SDimitry Andric   // Encapsulates access to the input file and any dependent type server,
7606c3fb27SDimitry Andric   // including any precompiled header object.
7706c3fb27SDimitry Andric   llvm::pdb::InputFile Input;
7806c3fb27SDimitry Andric   std::shared_ptr<llvm::pdb::InputFile> TypeServer;
7906c3fb27SDimitry Andric   std::shared_ptr<LazyRandomTypeCollection> PrecompHeader;
8006c3fb27SDimitry Andric 
8106c3fb27SDimitry Andric   // Persistance data when loading a type server.
8206c3fb27SDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = nullptr;
8306c3fb27SDimitry Andric   std::unique_ptr<MemoryBuffer> MemBuffer;
8406c3fb27SDimitry Andric   std::unique_ptr<llvm::pdb::IPDBSession> Session;
8506c3fb27SDimitry Andric   std::unique_ptr<llvm::pdb::NativeSession> PdbSession;
8606c3fb27SDimitry Andric 
8706c3fb27SDimitry Andric   // Persistance data when loading a precompiled header.
8806c3fb27SDimitry Andric   BumpPtrAllocator BuilderAllocator;
8906c3fb27SDimitry Andric   std::unique_ptr<AppendingTypeTableBuilder> Builder;
9006c3fb27SDimitry Andric   std::unique_ptr<BinaryItemStream<CVType>> ItemStream;
9106c3fb27SDimitry Andric   std::unique_ptr<BinaryStreamReader> ReaderPrecomp;
9206c3fb27SDimitry Andric   std::vector<CVType> TypeArray;
9306c3fb27SDimitry Andric   CVTypeArray TypeStream;
9406c3fb27SDimitry Andric   CVTypeArray CVTypesPrecomp;
9506c3fb27SDimitry Andric 
9606c3fb27SDimitry Andric   // Persistance data when loading an executable file.
9706c3fb27SDimitry Andric   std::unique_ptr<MemoryBuffer> BinaryBuffer;
9806c3fb27SDimitry Andric   std::unique_ptr<llvm::object::Binary> BinaryExecutable;
9906c3fb27SDimitry Andric 
10006c3fb27SDimitry Andric   Error loadTargetInfo(const object::ObjectFile &Obj);
10106c3fb27SDimitry Andric   Error loadTargetInfo(const llvm::pdb::PDBFile &Pdb);
10206c3fb27SDimitry Andric 
10306c3fb27SDimitry Andric   void mapRangeAddress(const object::ObjectFile &Obj,
10406c3fb27SDimitry Andric                        const object::SectionRef &Section,
10506c3fb27SDimitry Andric                        bool IsComdat) override;
10606c3fb27SDimitry Andric 
10706c3fb27SDimitry Andric   llvm::object::COFFObjectFile &getObj() { return Input.obj(); }
10806c3fb27SDimitry Andric   llvm::pdb::PDBFile &getPdb() { return Input.pdb(); }
10906c3fb27SDimitry Andric   bool isObj() const { return Input.isObj(); }
11006c3fb27SDimitry Andric   bool isPdb() const { return Input.isPdb(); }
11106c3fb27SDimitry Andric   StringRef getFileName() { return Input.getFilePath(); }
11206c3fb27SDimitry Andric 
11306c3fb27SDimitry Andric   // Pathname to executable image.
11406c3fb27SDimitry Andric   std::string ExePath;
11506c3fb27SDimitry Andric 
11606c3fb27SDimitry Andric   LVOffset CurrentOffset = 0;
11706c3fb27SDimitry Andric   int32_t CurrentModule = -1;
11806c3fb27SDimitry Andric 
11906c3fb27SDimitry Andric   using RelocMapTy = DenseMap<const llvm::object::coff_section *,
12006c3fb27SDimitry Andric                               std::vector<llvm::object::RelocationRef>>;
12106c3fb27SDimitry Andric   RelocMapTy RelocMap;
12206c3fb27SDimitry Andric 
12306c3fb27SDimitry Andric   // Object files have only one type stream that contains both types and ids.
12406c3fb27SDimitry Andric   // Precompiled header objects don't contain an IPI stream. Use the TPI.
12506c3fb27SDimitry Andric   LazyRandomTypeCollection &types() {
12606c3fb27SDimitry Andric     return TypeServer ? TypeServer->types()
12706c3fb27SDimitry Andric                       : (PrecompHeader ? *PrecompHeader : Input.types());
12806c3fb27SDimitry Andric   }
12906c3fb27SDimitry Andric   LazyRandomTypeCollection &ids() {
13006c3fb27SDimitry Andric     return TypeServer ? TypeServer->ids()
13106c3fb27SDimitry Andric                       : (PrecompHeader ? *PrecompHeader : Input.ids());
13206c3fb27SDimitry Andric   }
13306c3fb27SDimitry Andric 
13406c3fb27SDimitry Andric   LVLogicalVisitor LogicalVisitor;
13506c3fb27SDimitry Andric 
13606c3fb27SDimitry Andric   Expected<StringRef>
13706c3fb27SDimitry Andric   getFileNameForFileOffset(uint32_t FileOffset,
13806c3fb27SDimitry Andric                            const llvm::pdb::SymbolGroup *SG = nullptr);
13906c3fb27SDimitry Andric   void printRelocatedField(StringRef Label,
14006c3fb27SDimitry Andric                            const llvm::object::coff_section *CoffSection,
14106c3fb27SDimitry Andric                            uint32_t RelocOffset, uint32_t Offset,
14206c3fb27SDimitry Andric                            StringRef *RelocSym);
14306c3fb27SDimitry Andric 
14406c3fb27SDimitry Andric   Error printFileNameForOffset(StringRef Label, uint32_t FileOffset,
14506c3fb27SDimitry Andric                                const llvm::pdb::SymbolGroup *SG = nullptr);
14606c3fb27SDimitry Andric 
14706c3fb27SDimitry Andric   Error loadPrecompiledObject(PrecompRecord &Precomp, CVTypeArray &CVTypesObj);
14806c3fb27SDimitry Andric   Error loadTypeServer(TypeServer2Record &TS);
14906c3fb27SDimitry Andric   Error traverseTypes(llvm::pdb::PDBFile &Pdb, LazyRandomTypeCollection &Types,
15006c3fb27SDimitry Andric                       LazyRandomTypeCollection &Ids);
15106c3fb27SDimitry Andric 
15206c3fb27SDimitry Andric   Error collectInlineeInfo(DebugInlineeLinesSubsectionRef &Lines,
15306c3fb27SDimitry Andric                            const llvm::pdb::SymbolGroup *SG = nullptr);
15406c3fb27SDimitry Andric 
15506c3fb27SDimitry Andric   void cacheRelocations();
15606c3fb27SDimitry Andric   Error resolveSymbol(const llvm::object::coff_section *CoffSection,
15706c3fb27SDimitry Andric                       uint64_t Offset, llvm::object::SymbolRef &Sym);
15806c3fb27SDimitry Andric   Error resolveSymbolName(const llvm::object::coff_section *CoffSection,
15906c3fb27SDimitry Andric                           uint64_t Offset, StringRef &Name);
16006c3fb27SDimitry Andric   Error traverseTypeSection(StringRef SectionName,
16106c3fb27SDimitry Andric                             const llvm::object::SectionRef &Section);
16206c3fb27SDimitry Andric   Error traverseSymbolSection(StringRef SectionName,
16306c3fb27SDimitry Andric                               const llvm::object::SectionRef &Section);
16406c3fb27SDimitry Andric   Error traverseInlineeLines(StringRef Subsection);
16506c3fb27SDimitry Andric 
16606c3fb27SDimitry Andric   DebugChecksumsSubsectionRef CVFileChecksumTable;
16706c3fb27SDimitry Andric   DebugStringTableSubsectionRef CVStringTable;
16806c3fb27SDimitry Andric 
16906c3fb27SDimitry Andric   Error traverseSymbolsSubsection(StringRef Subsection,
17006c3fb27SDimitry Andric                                   const llvm::object::SectionRef &Section,
17106c3fb27SDimitry Andric                                   StringRef SectionContents);
17206c3fb27SDimitry Andric 
17306c3fb27SDimitry Andric   /// Given a .debug$S section, find the string table and file checksum table.
17406c3fb27SDimitry Andric   /// This function taken from (COFFDumper.cpp).
17506c3fb27SDimitry Andric   /// TODO: It can be moved to the COFF library.
17606c3fb27SDimitry Andric   Error initializeFileAndStringTables(BinaryStreamReader &Reader);
17706c3fb27SDimitry Andric 
17806c3fb27SDimitry Andric   Error createLines(const FixedStreamArray<LineNumberEntry> &LineNumbers,
17906c3fb27SDimitry Andric                     LVAddress Addendum, uint32_t Segment, uint32_t Begin,
18006c3fb27SDimitry Andric                     uint32_t Size, uint32_t NameIndex,
18106c3fb27SDimitry Andric                     const llvm::pdb::SymbolGroup *SG = nullptr);
18206c3fb27SDimitry Andric   Error createScopes(llvm::object::COFFObjectFile &Obj);
18306c3fb27SDimitry Andric   Error createScopes(llvm::pdb::PDBFile &Pdb);
18406c3fb27SDimitry Andric   Error processModule();
18506c3fb27SDimitry Andric 
18606c3fb27SDimitry Andric protected:
18706c3fb27SDimitry Andric   Error createScopes() override;
18806c3fb27SDimitry Andric   void sortScopes() override;
18906c3fb27SDimitry Andric 
19006c3fb27SDimitry Andric public:
19106c3fb27SDimitry Andric   LVCodeViewReader() = delete;
19206c3fb27SDimitry Andric   LVCodeViewReader(StringRef Filename, StringRef FileFormatName,
19306c3fb27SDimitry Andric                    llvm::object::COFFObjectFile &Obj, ScopedPrinter &W,
19406c3fb27SDimitry Andric                    StringRef ExePath)
19506c3fb27SDimitry Andric       : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF),
19606c3fb27SDimitry Andric         Input(&Obj), ExePath(ExePath), LogicalVisitor(this, W, Input) {}
19706c3fb27SDimitry Andric   LVCodeViewReader(StringRef Filename, StringRef FileFormatName,
19806c3fb27SDimitry Andric                    llvm::pdb::PDBFile &Pdb, ScopedPrinter &W, StringRef ExePath)
19906c3fb27SDimitry Andric       : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF),
20006c3fb27SDimitry Andric         Input(&Pdb), ExePath(ExePath), LogicalVisitor(this, W, Input) {}
20106c3fb27SDimitry Andric   LVCodeViewReader(const LVCodeViewReader &) = delete;
20206c3fb27SDimitry Andric   LVCodeViewReader &operator=(const LVCodeViewReader &) = delete;
20306c3fb27SDimitry Andric   ~LVCodeViewReader() = default;
20406c3fb27SDimitry Andric 
20506c3fb27SDimitry Andric   void getLinkageName(const llvm::object::coff_section *CoffSection,
20606c3fb27SDimitry Andric                       uint32_t RelocOffset, uint32_t Offset,
20706c3fb27SDimitry Andric                       StringRef *RelocSym);
20806c3fb27SDimitry Andric 
20906c3fb27SDimitry Andric   void addModule(LVScope *Scope) { Modules.push_back(Scope); }
21006c3fb27SDimitry Andric   LVScope *getScopeForModule(uint32_t Modi) {
21106c3fb27SDimitry Andric     return Modi >= Modules.size() ? nullptr : Modules[Modi];
21206c3fb27SDimitry Andric   }
21306c3fb27SDimitry Andric 
21406c3fb27SDimitry Andric   // Get the string representation for the CodeView symbols.
21506c3fb27SDimitry Andric   static StringRef getSymbolKindName(SymbolKind Kind);
21606c3fb27SDimitry Andric   static std::string formatRegisterId(RegisterId Register, CPUType CPU);
21706c3fb27SDimitry Andric 
21806c3fb27SDimitry Andric   std::string getRegisterName(LVSmall Opcode,
21906c3fb27SDimitry Andric                               ArrayRef<uint64_t> Operands) override;
22006c3fb27SDimitry Andric 
22106c3fb27SDimitry Andric   bool isSystemEntry(LVElement *Element, StringRef Name) const override;
22206c3fb27SDimitry Andric 
22306c3fb27SDimitry Andric   void print(raw_ostream &OS) const;
22406c3fb27SDimitry Andric   void printRecords(raw_ostream &OS) const override {
22506c3fb27SDimitry Andric     LogicalVisitor.printRecords(OS);
22606c3fb27SDimitry Andric   };
22706c3fb27SDimitry Andric 
22806c3fb27SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
22906c3fb27SDimitry Andric   void dump() const { print(dbgs()); }
23006c3fb27SDimitry Andric #endif
23106c3fb27SDimitry Andric };
23206c3fb27SDimitry Andric 
23306c3fb27SDimitry Andric } // end namespace logicalview
23406c3fb27SDimitry Andric } // end namespace llvm
23506c3fb27SDimitry Andric 
23606c3fb27SDimitry Andric #endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H
237