1 //===-- DebugNamesDWARFIndex.cpp -------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h"
11 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
12 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
13 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
14 #include "lldb/Utility/RegularExpression.h"
15 #include "lldb/Utility/Stream.h"
17 using namespace lldb_private;
20 static llvm::DWARFDataExtractor ToLLVM(const DWARFDataExtractor &data) {
21 return llvm::DWARFDataExtractor(
22 llvm::StringRef(reinterpret_cast<const char *>(data.GetDataStart()),
24 data.GetByteOrder() == eByteOrderLittle, data.GetAddressByteSize());
27 llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
28 DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names,
29 DWARFDataExtractor debug_str,
30 DWARFDebugInfo *debug_info) {
32 return llvm::make_error<llvm::StringError>("debug info null",
33 llvm::inconvertibleErrorCode());
36 llvm::make_unique<DebugNames>(ToLLVM(debug_names), ToLLVM(debug_str));
37 if (llvm::Error E = index_up->extract())
40 return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex(
41 module, std::move(index_up), debug_names, debug_str, *debug_info));
44 llvm::DenseSet<dw_offset_t>
45 DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) {
46 llvm::DenseSet<dw_offset_t> result;
47 for (const DebugNames::NameIndex &ni : debug_names) {
48 for (uint32_t cu = 0; cu < ni.getCUCount(); ++cu)
49 result.insert(ni.getCUOffset(cu));
54 DIERef DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) {
55 llvm::Optional<uint64_t> cu_offset = entry.getCUOffset();
59 DWARFUnit *cu = m_debug_info.GetCompileUnit(*cu_offset);
63 // This initializes the DWO symbol file. It's not possible for
64 // GetDwoSymbolFile to call this automatically because of mutual recursion
65 // between this and DWARFDebugInfoEntry::GetAttributeValue.
66 cu->ExtractUnitDIEIfNeeded();
67 uint64_t die_bias = cu->GetDwoSymbolFile() ? 0 : *cu_offset;
69 if (llvm::Optional<uint64_t> die_offset = entry.getDIEUnitOffset())
70 return DIERef(*cu_offset, die_bias + *die_offset);
75 void DebugNamesDWARFIndex::Append(const DebugNames::Entry &entry,
77 if (DIERef ref = ToDIERef(entry))
78 offsets.push_back(ref);
81 void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error,
82 const DebugNames::NameIndex &ni,
83 llvm::StringRef name) {
84 // Ignore SentinelErrors, log everything else.
86 LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS),
87 handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}),
88 "Failed to parse index entries for index at {1:x}, name {2}: {0}",
89 ni.getUnitOffset(), name);
92 void DebugNamesDWARFIndex::GetGlobalVariables(ConstString basename,
94 m_fallback.GetGlobalVariables(basename, offsets);
96 for (const DebugNames::Entry &entry :
97 m_debug_names_up->equal_range(basename.GetStringRef())) {
98 if (entry.tag() != DW_TAG_variable)
101 Append(entry, offsets);
105 void DebugNamesDWARFIndex::GetGlobalVariables(const RegularExpression ®ex,
107 m_fallback.GetGlobalVariables(regex, offsets);
109 for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
110 for (DebugNames::NameTableEntry nte: ni) {
111 if (!regex.Execute(nte.getString()))
114 uint32_t entry_offset = nte.getEntryOffset();
115 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
116 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
117 if (entry_or->tag() != DW_TAG_variable)
120 Append(*entry_or, offsets);
122 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
127 void DebugNamesDWARFIndex::GetGlobalVariables(const DWARFUnit &cu,
129 m_fallback.GetGlobalVariables(cu, offsets);
131 uint64_t cu_offset = cu.GetOffset();
132 for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
133 for (DebugNames::NameTableEntry nte: ni) {
134 uint32_t entry_offset = nte.getEntryOffset();
135 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
136 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
137 if (entry_or->tag() != DW_TAG_variable)
139 if (entry_or->getCUOffset() != cu_offset)
142 Append(*entry_or, offsets);
144 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
149 void DebugNamesDWARFIndex::GetCompleteObjCClass(ConstString class_name,
150 bool must_be_implementation,
152 m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, offsets);
154 // Keep a list of incomplete types as fallback for when we don't find the
156 DIEArray incomplete_types;
158 for (const DebugNames::Entry &entry :
159 m_debug_names_up->equal_range(class_name.GetStringRef())) {
160 if (entry.tag() != DW_TAG_structure_type &&
161 entry.tag() != DW_TAG_class_type)
164 DIERef ref = ToDIERef(entry);
168 DWARFUnit *cu = m_debug_info.GetCompileUnit(ref.cu_offset);
169 if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) {
170 incomplete_types.push_back(ref);
174 // FIXME: We should return DWARFDIEs so we don't have to resolve it twice.
175 DWARFDIE die = m_debug_info.GetDIE(ref);
179 if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) {
180 // If we find the complete version we're done.
181 offsets.push_back(ref);
184 incomplete_types.push_back(ref);
188 offsets.insert(offsets.end(), incomplete_types.begin(),
189 incomplete_types.end());
192 void DebugNamesDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) {
193 m_fallback.GetTypes(name, offsets);
195 for (const DebugNames::Entry &entry :
196 m_debug_names_up->equal_range(name.GetStringRef())) {
197 if (isType(entry.tag()))
198 Append(entry, offsets);
202 void DebugNamesDWARFIndex::GetTypes(const DWARFDeclContext &context,
204 m_fallback.GetTypes(context, offsets);
206 for (const DebugNames::Entry &entry :
207 m_debug_names_up->equal_range(context[0].name)) {
208 if (entry.tag() == context[0].tag)
209 Append(entry, offsets);
213 void DebugNamesDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {
214 m_fallback.GetNamespaces(name, offsets);
216 for (const DebugNames::Entry &entry :
217 m_debug_names_up->equal_range(name.GetStringRef())) {
218 if (entry.tag() == DW_TAG_namespace)
219 Append(entry, offsets);
223 void DebugNamesDWARFIndex::GetFunctions(
224 ConstString name, DWARFDebugInfo &info,
225 const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
226 std::vector<DWARFDIE> &dies) {
228 std::vector<DWARFDIE> v;
229 m_fallback.GetFunctions(name, info, parent_decl_ctx, name_type_mask, v);
231 for (const DebugNames::Entry &entry :
232 m_debug_names_up->equal_range(name.GetStringRef())) {
233 Tag tag = entry.tag();
234 if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
237 if (DIERef ref = ToDIERef(entry))
238 ProcessFunctionDIE(name.GetStringRef(), ref, info, parent_decl_ctx,
242 std::set<DWARFDebugInfoEntry *> seen;
243 for (DWARFDIE die : v)
244 if (seen.insert(die.GetDIE()).second)
248 void DebugNamesDWARFIndex::GetFunctions(const RegularExpression ®ex,
250 m_fallback.GetFunctions(regex, offsets);
252 for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
253 for (DebugNames::NameTableEntry nte: ni) {
254 if (!regex.Execute(nte.getString()))
257 uint32_t entry_offset = nte.getEntryOffset();
258 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
259 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
260 Tag tag = entry_or->tag();
261 if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
264 Append(*entry_or, offsets);
266 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
271 void DebugNamesDWARFIndex::Dump(Stream &s) {
275 llvm::raw_string_ostream os(data);
276 m_debug_names_up->dump(os);
277 s.PutCString(os.str());