1 //===-- LVBinaryReader.h ----------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the LVBinaryReader class, which is used to describe a
10 // binary reader.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVBINARYREADER_H
15 #define LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVBINARYREADER_H
16 
17 #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
21 #include "llvm/MC/MCInstPrinter.h"
22 #include "llvm/MC/MCInstrInfo.h"
23 #include "llvm/MC/MCObjectFileInfo.h"
24 #include "llvm/MC/MCRegisterInfo.h"
25 #include "llvm/MC/MCSubtargetInfo.h"
26 #include "llvm/MC/TargetRegistry.h"
27 #include "llvm/Object/ObjectFile.h"
28 
29 namespace llvm {
30 namespace logicalview {
31 
32 constexpr bool UpdateHighAddress = false;
33 
34 // Logical scope, Section address, Section index, IsComdat.
35 struct LVSymbolTableEntry final {
36   LVScope *Scope = nullptr;
37   LVAddress Address = 0;
38   LVSectionIndex SectionIndex = 0;
39   bool IsComdat = false;
40   LVSymbolTableEntry() = default;
41   LVSymbolTableEntry(LVScope *Scope, LVAddress Address,
42                      LVSectionIndex SectionIndex, bool IsComdat)
43       : Scope(Scope), Address(Address), SectionIndex(SectionIndex),
44         IsComdat(IsComdat) {}
45 };
46 
47 // Function names extracted from the object symbol table.
48 class LVSymbolTable final {
49   using LVSymbolNames = std::map<std::string, LVSymbolTableEntry>;
50   LVSymbolNames SymbolNames;
51 
52 public:
53   LVSymbolTable() = default;
54 
55   void add(StringRef Name, LVScope *Function, LVSectionIndex SectionIndex = 0);
56   void add(StringRef Name, LVAddress Address, LVSectionIndex SectionIndex,
57            bool IsComdat);
58   LVSectionIndex update(LVScope *Function);
59 
60   const LVSymbolTableEntry &getEntry(StringRef Name);
61   LVAddress getAddress(StringRef Name);
62   LVSectionIndex getIndex(StringRef Name);
63   bool getIsComdat(StringRef Name);
64 
65   void print(raw_ostream &OS);
66 };
67 
68 class LVBinaryReader : public LVReader {
69   // Function names extracted from the object symbol table.
70   LVSymbolTable SymbolTable;
71 
72   // Instruction lines for a logical scope. These instructions are fetched
73   // during its merge with the debug lines.
74   LVDoubleMap<LVSectionIndex, LVScope *, LVLines *> ScopeInstructions;
75 
76   // Links the scope with its first assembler address line.
77   LVDoubleMap<LVSectionIndex, LVAddress, LVScope *> AssemblerMappings;
78 
79   // Mapping from virtual address to section.
80   // The virtual address refers to the address where the section is loaded.
81   using LVSectionAddresses = std::map<LVSectionIndex, object::SectionRef>;
82   LVSectionAddresses SectionAddresses;
83 
84   void addSectionAddress(const object::SectionRef &Section) {
85     if (SectionAddresses.find(Section.getAddress()) == SectionAddresses.end())
86       SectionAddresses.emplace(Section.getAddress(), Section);
87   }
88 
89   // Scopes with ranges for current compile unit. It is used to find a line
90   // giving its exact or closest address. To support comdat functions, all
91   // addresses for the same section are recorded in the same map.
92   using LVSectionRanges = std::map<LVSectionIndex, LVRange *>;
93   LVSectionRanges SectionRanges;
94 
95   // Image base and virtual address for Executable file.
96   uint64_t ImageBaseAddress = 0;
97   uint64_t VirtualAddress = 0;
98 
99   // Object sections with machine code.
100   using LVSections = std::map<LVSectionIndex, object::SectionRef>;
101   LVSections Sections;
102 
103 protected:
104   // It contains the LVLineDebug elements representing the logical lines for
105   // the current compile unit, created by parsing the debug line section.
106   LVLines CULines;
107 
108   std::unique_ptr<const MCRegisterInfo> MRI;
109   std::unique_ptr<const MCAsmInfo> MAI;
110   std::unique_ptr<const MCSubtargetInfo> STI;
111   std::unique_ptr<const MCInstrInfo> MII;
112   std::unique_ptr<const MCDisassembler> MD;
113   std::unique_ptr<MCContext> MC;
114   std::unique_ptr<MCInstPrinter> MIP;
115 
116   // Loads all info for the architecture of the provided object file.
117   Error loadGenericTargetInfo(StringRef TheTriple, StringRef TheFeatures);
118 
119   virtual void mapRangeAddress(const object::ObjectFile &Obj) {}
120   virtual void mapRangeAddress(const object::ObjectFile &Obj,
121                                const object::SectionRef &Section,
122                                bool IsComdat) {}
123 
124   // Create a mapping from virtual address to section.
125   void mapVirtualAddress(const object::ObjectFile &Obj);
126   void mapVirtualAddress(const object::COFFObjectFile &COFFObj);
127 
128   Expected<std::pair<LVSectionIndex, object::SectionRef>>
129   getSection(LVScope *Scope, LVAddress Address, LVSectionIndex SectionIndex);
130 
131   void addSectionRange(LVSectionIndex SectionIndex, LVScope *Scope);
132   void addSectionRange(LVSectionIndex SectionIndex, LVScope *Scope,
133                        LVAddress LowerAddress, LVAddress UpperAddress);
134   LVRange *getSectionRanges(LVSectionIndex SectionIndex);
135 
136   Error createInstructions();
137   Error createInstructions(LVScope *Function, LVSectionIndex SectionIndex);
138   Error createInstructions(LVScope *Function, LVSectionIndex SectionIndex,
139                            const LVNameInfo &NameInfo);
140 
141   void processLines(LVLines *DebugLines, LVSectionIndex SectionIndex);
142   void processLines(LVLines *DebugLines, LVSectionIndex SectionIndex,
143                     LVScope *Function);
144 
145 public:
146   LVBinaryReader() = delete;
147   LVBinaryReader(StringRef Filename, StringRef FileFormatName, ScopedPrinter &W,
148                  LVBinaryType BinaryType)
149       : LVReader(Filename, FileFormatName, W, BinaryType) {}
150   LVBinaryReader(const LVBinaryReader &) = delete;
151   LVBinaryReader &operator=(const LVBinaryReader &) = delete;
152   virtual ~LVBinaryReader();
153 
154   void addToSymbolTable(StringRef Name, LVScope *Function,
155                         LVSectionIndex SectionIndex = 0);
156   void addToSymbolTable(StringRef Name, LVAddress Address,
157                         LVSectionIndex SectionIndex, bool IsComdat);
158   LVSectionIndex updateSymbolTable(LVScope *Function);
159 
160   const LVSymbolTableEntry &getSymbolTableEntry(StringRef Name);
161   LVAddress getSymbolTableAddress(StringRef Name);
162   LVSectionIndex getSymbolTableIndex(StringRef Name);
163   bool getSymbolTableIsComdat(StringRef Name);
164 
165   LVSectionIndex getSectionIndex(LVScope *Scope) override {
166     return Scope ? getSymbolTableIndex(Scope->getLinkageName())
167                  : DotTextSectionIndex;
168   }
169 
170   void print(raw_ostream &OS) const;
171 
172 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
173   void dump() const { print(dbgs()); }
174 #endif
175 };
176 
177 } // end namespace logicalview
178 } // end namespace llvm
179 
180 #endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVBINARYREADER_H
181