1 //===-- LVELFReader.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 LVELFReader class, which is used to describe a
10 // debug information (DWARF) reader.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVELFREADER_H
15 #define LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVELFREADER_H
16 
17 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
18 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
19 #include "llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h"
20 #include <unordered_set>
21 
22 namespace llvm {
23 namespace logicalview {
24 
25 class LVElement;
26 class LVLine;
27 class LVScopeCompileUnit;
28 class LVSymbol;
29 class LVType;
30 
31 using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec;
32 
33 class LVELFReader final : public LVBinaryReader {
34   object::ObjectFile &Obj;
35 
36   // Indicates if ranges data are available; in the case of split DWARF any
37   // reference to ranges is valid only if the skeleton DIE has been loaded.
38   bool RangesDataAvailable = false;
39   LVAddress CUBaseAddress = 0;
40   LVAddress CUHighAddress = 0;
41 
42   // Current elements during the processing of a DIE.
43   LVElement *CurrentElement = nullptr;
44   LVScope *CurrentScope = nullptr;
45   LVSymbol *CurrentSymbol = nullptr;
46   LVType *CurrentType = nullptr;
47   LVOffset CurrentOffset = 0;
48   LVOffset CurrentEndOffset = 0;
49 
50   // In DWARF v4, the files are 1-indexed.
51   // In DWARF v5, the files are 0-indexed.
52   // The ELF reader expects the indexes as 1-indexed.
53   bool IncrementFileIndex = false;
54 
55   // Address ranges collected for current DIE.
56   std::vector<LVAddressRange> CurrentRanges;
57 
58   // Symbols with locations for current compile unit.
59   LVSymbols SymbolsWithLocations;
60 
61   // Global Offsets (Offset, Element).
62   LVOffsetElementMap GlobalOffsets;
63 
64   // Low PC and High PC values for DIE being processed.
65   LVAddress CurrentLowPC = 0;
66   LVAddress CurrentHighPC = 0;
67   bool FoundLowPC = false;
68   bool FoundHighPC = false;
69 
70   // Cross references (Elements).
71   using LVElementSet = std::unordered_set<LVElement *>;
72   struct LVElementEntry {
73     LVElement *Element;
74     LVElementSet References;
75     LVElementSet Types;
76     LVElementEntry(LVElement *Element = nullptr) : Element(Element) {}
77   };
78   using LVElementReference = std::unordered_map<LVOffset, LVElementEntry>;
79   LVElementReference ElementTable;
80 
81   Error loadTargetInfo(const object::ObjectFile &Obj);
82 
83   void mapRangeAddress(const object::ObjectFile &Obj) override;
84 
85   LVElement *createElement(dwarf::Tag Tag);
86   void traverseDieAndChildren(DWARFDie &DIE, LVScope *Parent,
87                               DWARFDie &SkeletonDie);
88   // Process the attributes for the given DIE.
89   LVScope *processOneDie(const DWARFDie &InputDIE, LVScope *Parent,
90                          DWARFDie &SkeletonDie);
91   void processOneAttribute(const DWARFDie &Die, LVOffset *OffsetPtr,
92                            const AttributeSpec &AttrSpec);
93   void createLineAndFileRecords(const DWARFDebugLine::LineTable *Lines);
94   void processLocationGaps();
95 
96   // Add offset to global map.
97   void addGlobalOffset(LVOffset Offset) {
98     if (GlobalOffsets.find(Offset) == GlobalOffsets.end())
99       // Just associate the DIE offset with a null element, as we do not
100       // know if the referenced element has been created.
101       GlobalOffsets.emplace(Offset, nullptr);
102   }
103 
104   // Remove offset from global map.
105   void removeGlobalOffset(LVOffset Offset) {
106     LVOffsetElementMap::iterator Iter = GlobalOffsets.find(Offset);
107     if (Iter != GlobalOffsets.end())
108       GlobalOffsets.erase(Iter);
109   }
110 
111   // Get the location information for DW_AT_data_member_location.
112   void processLocationMember(dwarf::Attribute Attr,
113                              const DWARFFormValue &FormValue,
114                              const DWARFDie &Die, uint64_t OffsetOnEntry);
115   void processLocationList(dwarf::Attribute Attr,
116                            const DWARFFormValue &FormValue, const DWARFDie &Die,
117                            uint64_t OffsetOnEntry,
118                            bool CallSiteLocation = false);
119   void updateReference(dwarf::Attribute Attr, const DWARFFormValue &FormValue);
120 
121   // Get an element given the DIE offset.
122   LVElement *getElementForOffset(LVOffset offset, LVElement *Element,
123                                  bool IsType);
124 
125 protected:
126   Error createScopes() override;
127   void sortScopes() override;
128 
129 public:
130   LVELFReader() = delete;
131   LVELFReader(StringRef Filename, StringRef FileFormatName,
132               object::ObjectFile &Obj, ScopedPrinter &W)
133       : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::ELF),
134         Obj(Obj) {}
135   LVELFReader(const LVELFReader &) = delete;
136   LVELFReader &operator=(const LVELFReader &) = delete;
137   ~LVELFReader() = default;
138 
139   LVAddress getCUBaseAddress() const { return CUBaseAddress; }
140   void setCUBaseAddress(LVAddress Address) { CUBaseAddress = Address; }
141   LVAddress getCUHighAddress() const { return CUHighAddress; }
142   void setCUHighAddress(LVAddress Address) { CUHighAddress = Address; }
143 
144   const LVSymbols &GetSymbolsWithLocations() const {
145     return SymbolsWithLocations;
146   }
147 
148   std::string getRegisterName(LVSmall Opcode,
149                               ArrayRef<uint64_t> Operands) override;
150 
151   void print(raw_ostream &OS) const;
152 
153 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
154   void dump() const { print(dbgs()); }
155 #endif
156 };
157 
158 } // end namespace logicalview
159 } // end namespace llvm
160 
161 #endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVELFREADER_H
162