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