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
22namespace llvm {
23namespace logicalview {
24
25class LVElement;
26class LVLine;
27class LVScopeCompileUnit;
28class LVSymbol;
29class LVType;
30
31using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec;
32
33class 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
125protected:
126  Error createScopes() override;
127  void sortScopes() override;
128
129public:
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