LLDB  mainline
DebugNamesDWARFIndex.cpp
Go to the documentation of this file.
1 //===-- DebugNamesDWARFIndex.cpp -------------------------------*- 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 
14 #include "lldb/Utility/Stream.h"
15 
16 using namespace lldb_private;
17 using namespace lldb;
18 
19 static llvm::DWARFDataExtractor ToLLVM(const DWARFDataExtractor &data) {
20  return llvm::DWARFDataExtractor(
21  llvm::StringRef(reinterpret_cast<const char *>(data.GetDataStart()),
22  data.GetByteSize()),
24 }
25 
26 llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
28  DWARFDataExtractor debug_str,
29  DWARFDebugInfo *debug_info) {
30  if (!debug_info) {
31  return llvm::make_error<llvm::StringError>("debug info null",
32  llvm::inconvertibleErrorCode());
33  }
34  auto index_up =
35  llvm::make_unique<DebugNames>(ToLLVM(debug_names), ToLLVM(debug_str));
36  if (llvm::Error E = index_up->extract())
37  return std::move(E);
38 
39  return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex(
40  module, std::move(index_up), debug_names, debug_str, *debug_info));
41 }
42 
43 llvm::DenseSet<dw_offset_t>
44 DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) {
45  llvm::DenseSet<dw_offset_t> result;
46  for (const DebugNames::NameIndex &ni : debug_names) {
47  for (uint32_t cu = 0; cu < ni.getCUCount(); ++cu)
48  result.insert(ni.getCUOffset(cu));
49  }
50  return result;
51 }
52 
53 DIERef DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) {
54  llvm::Optional<uint64_t> cu_offset = entry.getCUOffset();
55  if (!cu_offset)
56  return DIERef();
57 
58  DWARFUnit *cu = m_debug_info.GetCompileUnitAtOffset(*cu_offset);
59  if (!cu)
60  return DIERef();
61 
62  // This initializes the DWO symbol file. It's not possible for
63  // GetDwoSymbolFile to call this automatically because of mutual recursion
64  // between this and DWARFDebugInfoEntry::GetAttributeValue.
66  uint64_t die_bias = cu->GetDwoSymbolFile() ? 0 : *cu_offset;
67 
68  if (llvm::Optional<uint64_t> die_offset = entry.getDIEUnitOffset())
69  return DIERef(*cu_offset, die_bias + *die_offset);
70 
71  return DIERef();
72 }
73 
74 void DebugNamesDWARFIndex::Append(const DebugNames::Entry &entry,
75  DIEArray &offsets) {
76  if (DIERef ref = ToDIERef(entry))
77  offsets.push_back(ref);
78 }
79 
80 void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error,
81  const DebugNames::NameIndex &ni,
82  llvm::StringRef name) {
83  // Ignore SentinelErrors, log everything else.
86  handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}),
87  "Failed to parse index entries for index at {1:x}, name {2}: {0}",
88  ni.getUnitOffset(), name);
89 }
90 
92  DIEArray &offsets) {
93  m_fallback.GetGlobalVariables(basename, offsets);
94 
95  for (const DebugNames::Entry &entry :
96  m_debug_names_up->equal_range(basename.GetStringRef())) {
97  if (entry.tag() != DW_TAG_variable)
98  continue;
99 
100  Append(entry, offsets);
101  }
102 }
103 
105  DIEArray &offsets) {
106  m_fallback.GetGlobalVariables(regex, offsets);
107 
108  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
109  for (DebugNames::NameTableEntry nte: ni) {
110  if (!regex.Execute(nte.getString()))
111  continue;
112 
113  uint32_t entry_offset = nte.getEntryOffset();
114  llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
115  for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
116  if (entry_or->tag() != DW_TAG_variable)
117  continue;
118 
119  Append(*entry_or, offsets);
120  }
121  MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
122  }
123  }
124 }
125 
127  DIEArray &offsets) {
128  m_fallback.GetGlobalVariables(cu, offsets);
129 
130  uint64_t cu_offset = cu.GetOffset();
131  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
132  for (DebugNames::NameTableEntry nte: ni) {
133  uint32_t entry_offset = nte.getEntryOffset();
134  llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
135  for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
136  if (entry_or->tag() != DW_TAG_variable)
137  continue;
138  if (entry_or->getCUOffset() != cu_offset)
139  continue;
140 
141  Append(*entry_or, offsets);
142  }
143  MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
144  }
145  }
146 }
147 
149  bool must_be_implementation,
150  DIEArray &offsets) {
151  m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, offsets);
152 
153  // Keep a list of incomplete types as fallback for when we don't find the
154  // complete type.
155  DIEArray incomplete_types;
156 
157  for (const DebugNames::Entry &entry :
158  m_debug_names_up->equal_range(class_name.GetStringRef())) {
159  if (entry.tag() != DW_TAG_structure_type &&
160  entry.tag() != DW_TAG_class_type)
161  continue;
162 
163  DIERef ref = ToDIERef(entry);
164  if (!ref)
165  continue;
166 
167  DWARFUnit *cu = m_debug_info.GetCompileUnitAtOffset(ref.cu_offset);
168  if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) {
169  incomplete_types.push_back(ref);
170  continue;
171  }
172 
173  // FIXME: We should return DWARFDIEs so we don't have to resolve it twice.
174  DWARFDIE die = m_debug_info.GetDIE(ref);
175  if (!die)
176  continue;
177 
178  if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) {
179  // If we find the complete version we're done.
180  offsets.push_back(ref);
181  return;
182  } else {
183  incomplete_types.push_back(ref);
184  }
185  }
186 
187  offsets.insert(offsets.end(), incomplete_types.begin(),
188  incomplete_types.end());
189 }
190 
192  m_fallback.GetTypes(name, offsets);
193 
194  for (const DebugNames::Entry &entry :
195  m_debug_names_up->equal_range(name.GetStringRef())) {
196  if (isType(entry.tag()))
197  Append(entry, offsets);
198  }
199 }
200 
202  DIEArray &offsets) {
203  m_fallback.GetTypes(context, offsets);
204 
205  for (const DebugNames::Entry &entry :
206  m_debug_names_up->equal_range(context[0].name)) {
207  if (entry.tag() == context[0].tag)
208  Append(entry, offsets);
209  }
210 }
211 
213  m_fallback.GetNamespaces(name, offsets);
214 
215  for (const DebugNames::Entry &entry :
216  m_debug_names_up->equal_range(name.GetStringRef())) {
217  if (entry.tag() == DW_TAG_namespace)
218  Append(entry, offsets);
219  }
220 }
221 
223  ConstString name, DWARFDebugInfo &info,
224  const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
225  std::vector<DWARFDIE> &dies) {
226 
227  std::vector<DWARFDIE> v;
228  m_fallback.GetFunctions(name, info, parent_decl_ctx, name_type_mask, v);
229 
230  for (const DebugNames::Entry &entry :
231  m_debug_names_up->equal_range(name.GetStringRef())) {
232  Tag tag = entry.tag();
233  if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
234  continue;
235 
236  if (DIERef ref = ToDIERef(entry))
237  ProcessFunctionDIE(name.GetStringRef(), ref, info, parent_decl_ctx,
238  name_type_mask, v);
239  }
240 
241  std::set<DWARFDebugInfoEntry *> seen;
242  for (DWARFDIE die : v)
243  if (seen.insert(die.GetDIE()).second)
244  dies.push_back(die);
245 }
246 
248  DIEArray &offsets) {
249  m_fallback.GetFunctions(regex, offsets);
250 
251  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
252  for (DebugNames::NameTableEntry nte: ni) {
253  if (!regex.Execute(nte.getString()))
254  continue;
255 
256  uint32_t entry_offset = nte.getEntryOffset();
257  llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
258  for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
259  Tag tag = entry_or->tag();
260  if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
261  continue;
262 
263  Append(*entry_or, offsets);
264  }
265  MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
266  }
267  }
268 }
269 
271  m_fallback.Dump(s);
272 
273  std::string data;
274  llvm::raw_string_ostream os(data);
275  m_debug_names_up->dump(os);
276  s.PutCString(os.str());
277 }
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
void GetNamespaces(ConstString name, DIEArray &offsets) override
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
static llvm::Expected< std::unique_ptr< DebugNamesDWARFIndex > > Create(Module &module, DWARFDataExtractor debug_names, DWARFDataExtractor debug_str, DWARFDebugInfo *debug_info)
llvm::Error Error
void GetGlobalVariables(ConstString basename, DIEArray &offsets) override
Finds global variables with the given base name.
static Log * GetLogIfAll(uint32_t mask)
"lldb/Utility/RegularExpression.h" A C++ wrapper class for regex.
Definition: DIERef.h:18
#define LLDB_LOG_ERROR(log, error,...)
Definition: Log.h:225
std::vector< DIERef > DIEArray
Definition: DIERef.h:51
void GetTypes(ConstString name, DIEArray &offsets) override
#define DWARF_LOG_LOOKUPS
A class that describes an executable image and its associated object and symbol files.
Definition: Module.h:109
lldb::ByteOrder GetByteOrder() const
Get the current byte order value.
uint64_t GetAttributeValueAsUnsigned(const dw_attr_t attr, uint64_t fail_value) const
static llvm::DWARFDataExtractor ToLLVM(const DWARFDataExtractor &data)
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:233
void GetFunctions(ConstString name, DWARFDebugInfo &info, const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, std::vector< DWARFDIE > &dies) override
dw_offset_t GetOffset() const
Definition: DWARFUnit.h:76
uint64_t GetByteSize() const
Get the number of bytes contained in this object.
void ExtractUnitDIEIfNeeded()
Definition: DWARFUnit.cpp:38
bool Supports_DW_AT_APPLE_objc_complete_type()
Definition: DWARFUnit.cpp:570
dw_offset_t cu_offset
Definition: DIERef.h:47
const uint8_t * GetDataStart() const
Get the data start pointer.
A uniqued constant string class.
Definition: ConstString.h:38
bool Execute(llvm::StringRef string, Match *match=nullptr) const
Executes a regular expression.
void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, DIEArray &offsets) override
char * basename(char *path)
DWARFDIE GetDIE(dw_offset_t die_offset) const
Definition: DWARFDIE.cpp:124
Definition: SBAddress.h:15
SymbolFileDWARFDwo * GetDwoSymbolFile() const
Definition: DWARFUnit.cpp:767
uint32_t GetAddressByteSize() const
Get the current address size.