File: | tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp |
Location: | line 1082, column 17 |
Description: | Function call argument is an uninitialized value |
1 | //===-- SymbolFileDWARF.cpp ------------------------------------*- C++ -*-===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | ||||
10 | #include "SymbolFileDWARF.h" | |||
11 | ||||
12 | // Other libraries and framework includes | |||
13 | #include "llvm/Support/Casting.h" | |||
14 | ||||
15 | #include "lldb/Core/ArchSpec.h" | |||
16 | #include "lldb/Core/Module.h" | |||
17 | #include "lldb/Core/ModuleList.h" | |||
18 | #include "lldb/Core/ModuleSpec.h" | |||
19 | #include "lldb/Core/PluginManager.h" | |||
20 | #include "lldb/Core/RegularExpression.h" | |||
21 | #include "lldb/Core/Scalar.h" | |||
22 | #include "lldb/Core/Section.h" | |||
23 | #include "lldb/Core/StreamFile.h" | |||
24 | #include "lldb/Core/StreamString.h" | |||
25 | #include "lldb/Core/Timer.h" | |||
26 | #include "lldb/Core/Value.h" | |||
27 | ||||
28 | #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" | |||
29 | ||||
30 | #include "lldb/Host/FileSystem.h" | |||
31 | #include "lldb/Host/Host.h" | |||
32 | ||||
33 | #include "lldb/Interpreter/OptionValueFileSpecList.h" | |||
34 | #include "lldb/Interpreter/OptionValueProperties.h" | |||
35 | ||||
36 | #include "lldb/Symbol/Block.h" | |||
37 | #include "lldb/Symbol/ClangASTContext.h" | |||
38 | #include "lldb/Symbol/CompilerDecl.h" | |||
39 | #include "lldb/Symbol/CompilerDeclContext.h" | |||
40 | #include "lldb/Symbol/CompileUnit.h" | |||
41 | #include "lldb/Symbol/LineTable.h" | |||
42 | #include "lldb/Symbol/ObjectFile.h" | |||
43 | #include "lldb/Symbol/SymbolVendor.h" | |||
44 | #include "lldb/Symbol/TypeSystem.h" | |||
45 | #include "lldb/Symbol/VariableList.h" | |||
46 | #include "lldb/Symbol/TypeMap.h" | |||
47 | ||||
48 | #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" | |||
49 | #include "Plugins/Language/ObjC/ObjCLanguage.h" | |||
50 | ||||
51 | #include "lldb/Target/Language.h" | |||
52 | ||||
53 | #include "lldb/Utility/TaskPool.h" | |||
54 | ||||
55 | #include "DWARFASTParser.h" | |||
56 | #include "DWARFCompileUnit.h" | |||
57 | #include "DWARFDebugAbbrev.h" | |||
58 | #include "DWARFDebugAranges.h" | |||
59 | #include "DWARFDebugInfo.h" | |||
60 | #include "DWARFDebugLine.h" | |||
61 | #include "DWARFDebugPubnames.h" | |||
62 | #include "DWARFDebugRanges.h" | |||
63 | #include "DWARFDeclContext.h" | |||
64 | #include "DWARFDIECollection.h" | |||
65 | #include "DWARFFormValue.h" | |||
66 | #include "LogChannelDWARF.h" | |||
67 | #include "SymbolFileDWARFDwo.h" | |||
68 | #include "SymbolFileDWARFDebugMap.h" | |||
69 | ||||
70 | #include <map> | |||
71 | ||||
72 | #include <ctype.h> | |||
73 | #include <string.h> | |||
74 | ||||
75 | //#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN | |||
76 | ||||
77 | #ifdef ENABLE_DEBUG_PRINTF | |||
78 | #include <stdio.h> | |||
79 | #define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__) | |||
80 | #else | |||
81 | #define DEBUG_PRINTF(fmt, ...) | |||
82 | #endif | |||
83 | ||||
84 | using namespace lldb; | |||
85 | using namespace lldb_private; | |||
86 | ||||
87 | //static inline bool | |||
88 | //child_requires_parent_class_union_or_struct_to_be_completed (dw_tag_t tag) | |||
89 | //{ | |||
90 | // switch (tag) | |||
91 | // { | |||
92 | // default: | |||
93 | // break; | |||
94 | // case DW_TAG_subprogram: | |||
95 | // case DW_TAG_inlined_subroutine: | |||
96 | // case DW_TAG_class_type: | |||
97 | // case DW_TAG_structure_type: | |||
98 | // case DW_TAG_union_type: | |||
99 | // return true; | |||
100 | // } | |||
101 | // return false; | |||
102 | //} | |||
103 | // | |||
104 | ||||
105 | namespace { | |||
106 | ||||
107 | PropertyDefinition | |||
108 | g_properties[] = | |||
109 | { | |||
110 | { "comp-dir-symlink-paths" , OptionValue::eTypeFileSpecList, true, 0 , nullptr, nullptr, "If the DW_AT_comp_dir matches any of these paths the symbolic links will be resolved at DWARF parse time." }, | |||
111 | { nullptr , OptionValue::eTypeInvalid , false, 0, nullptr, nullptr, nullptr } | |||
112 | }; | |||
113 | ||||
114 | enum | |||
115 | { | |||
116 | ePropertySymLinkPaths | |||
117 | }; | |||
118 | ||||
119 | ||||
120 | class PluginProperties : public Properties | |||
121 | { | |||
122 | public: | |||
123 | static ConstString | |||
124 | GetSettingName() | |||
125 | { | |||
126 | return SymbolFileDWARF::GetPluginNameStatic(); | |||
127 | } | |||
128 | ||||
129 | PluginProperties() | |||
130 | { | |||
131 | m_collection_sp.reset (new OptionValueProperties(GetSettingName())); | |||
132 | m_collection_sp->Initialize(g_properties); | |||
133 | } | |||
134 | ||||
135 | FileSpecList& | |||
136 | GetSymLinkPaths() | |||
137 | { | |||
138 | OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr, true, ePropertySymLinkPaths); | |||
139 | assert(option_value)((option_value) ? static_cast<void> (0) : __assert_fail ("option_value", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 139, __PRETTY_FUNCTION__)); | |||
140 | return option_value->GetCurrentValue(); | |||
141 | } | |||
142 | ||||
143 | }; | |||
144 | ||||
145 | typedef std::shared_ptr<PluginProperties> SymbolFileDWARFPropertiesSP; | |||
146 | ||||
147 | static const SymbolFileDWARFPropertiesSP& | |||
148 | GetGlobalPluginProperties() | |||
149 | { | |||
150 | static const auto g_settings_sp(std::make_shared<PluginProperties>()); | |||
151 | return g_settings_sp; | |||
152 | } | |||
153 | ||||
154 | } // anonymous namespace end | |||
155 | ||||
156 | ||||
157 | static const char* | |||
158 | removeHostnameFromPathname(const char* path_from_dwarf) | |||
159 | { | |||
160 | if (!path_from_dwarf || !path_from_dwarf[0]) | |||
161 | { | |||
162 | return path_from_dwarf; | |||
163 | } | |||
164 | ||||
165 | const char *colon_pos = strchr(path_from_dwarf, ':'); | |||
166 | if (nullptr == colon_pos) | |||
167 | { | |||
168 | return path_from_dwarf; | |||
169 | } | |||
170 | ||||
171 | const char *slash_pos = strchr(path_from_dwarf, '/'); | |||
172 | if (slash_pos && (slash_pos < colon_pos)) | |||
173 | { | |||
174 | return path_from_dwarf; | |||
175 | } | |||
176 | ||||
177 | // check whether we have a windows path, and so the first character | |||
178 | // is a drive-letter not a hostname. | |||
179 | if ( | |||
180 | colon_pos == path_from_dwarf + 1 && | |||
181 | isalpha(*path_from_dwarf) && | |||
182 | strlen(path_from_dwarf) > 2 && | |||
183 | '\\' == path_from_dwarf[2]) | |||
184 | { | |||
185 | return path_from_dwarf; | |||
186 | } | |||
187 | ||||
188 | return colon_pos + 1; | |||
189 | } | |||
190 | ||||
191 | static const char* | |||
192 | resolveCompDir(const char* path_from_dwarf) | |||
193 | { | |||
194 | if (!path_from_dwarf) | |||
195 | return nullptr; | |||
196 | ||||
197 | // DWARF2/3 suggests the form hostname:pathname for compilation directory. | |||
198 | // Remove the host part if present. | |||
199 | const char* local_path = removeHostnameFromPathname(path_from_dwarf); | |||
200 | if (!local_path) | |||
201 | return nullptr; | |||
202 | ||||
203 | bool is_symlink = false; | |||
204 | FileSpec local_path_spec(local_path, false); | |||
205 | const auto& file_specs = GetGlobalPluginProperties()->GetSymLinkPaths(); | |||
206 | for (size_t i = 0; i < file_specs.GetSize() && !is_symlink; ++i) | |||
207 | is_symlink = FileSpec::Equal(file_specs.GetFileSpecAtIndex(i), local_path_spec, true); | |||
208 | ||||
209 | if (!is_symlink) | |||
210 | return local_path; | |||
211 | ||||
212 | if (!local_path_spec.IsSymbolicLink()) | |||
213 | return local_path; | |||
214 | ||||
215 | FileSpec resolved_local_path_spec; | |||
216 | const auto error = FileSystem::Readlink(local_path_spec, resolved_local_path_spec); | |||
217 | if (error.Success()) | |||
218 | return resolved_local_path_spec.GetCString(); | |||
219 | ||||
220 | return nullptr; | |||
221 | } | |||
222 | ||||
223 | ||||
224 | void | |||
225 | SymbolFileDWARF::Initialize() | |||
226 | { | |||
227 | LogChannelDWARF::Initialize(); | |||
228 | PluginManager::RegisterPlugin (GetPluginNameStatic(), | |||
229 | GetPluginDescriptionStatic(), | |||
230 | CreateInstance, | |||
231 | DebuggerInitialize); | |||
232 | } | |||
233 | ||||
234 | void | |||
235 | SymbolFileDWARF::DebuggerInitialize(Debugger &debugger) | |||
236 | { | |||
237 | if (!PluginManager::GetSettingForSymbolFilePlugin(debugger, PluginProperties::GetSettingName())) | |||
238 | { | |||
239 | const bool is_global_setting = true; | |||
240 | PluginManager::CreateSettingForSymbolFilePlugin(debugger, | |||
241 | GetGlobalPluginProperties()->GetValueProperties(), | |||
242 | ConstString ("Properties for the dwarf symbol-file plug-in."), | |||
243 | is_global_setting); | |||
244 | } | |||
245 | } | |||
246 | ||||
247 | void | |||
248 | SymbolFileDWARF::Terminate() | |||
249 | { | |||
250 | PluginManager::UnregisterPlugin (CreateInstance); | |||
251 | LogChannelDWARF::Initialize(); | |||
252 | } | |||
253 | ||||
254 | ||||
255 | lldb_private::ConstString | |||
256 | SymbolFileDWARF::GetPluginNameStatic() | |||
257 | { | |||
258 | static ConstString g_name("dwarf"); | |||
259 | return g_name; | |||
260 | } | |||
261 | ||||
262 | const char * | |||
263 | SymbolFileDWARF::GetPluginDescriptionStatic() | |||
264 | { | |||
265 | return "DWARF and DWARF3 debug symbol file reader."; | |||
266 | } | |||
267 | ||||
268 | ||||
269 | SymbolFile* | |||
270 | SymbolFileDWARF::CreateInstance (ObjectFile* obj_file) | |||
271 | { | |||
272 | return new SymbolFileDWARF(obj_file); | |||
273 | } | |||
274 | ||||
275 | TypeList * | |||
276 | SymbolFileDWARF::GetTypeList () | |||
277 | { | |||
278 | if (GetDebugMapSymfile ()) | |||
279 | return m_debug_map_symfile->GetTypeList(); | |||
280 | return m_obj_file->GetModule()->GetTypeList(); | |||
281 | ||||
282 | } | |||
283 | void | |||
284 | SymbolFileDWARF::GetTypes (const DWARFDIE &die, | |||
285 | dw_offset_t min_die_offset, | |||
286 | dw_offset_t max_die_offset, | |||
287 | uint32_t type_mask, | |||
288 | TypeSet &type_set) | |||
289 | { | |||
290 | if (die) | |||
291 | { | |||
292 | const dw_offset_t die_offset = die.GetOffset(); | |||
293 | ||||
294 | if (die_offset >= max_die_offset) | |||
295 | return; | |||
296 | ||||
297 | if (die_offset >= min_die_offset) | |||
298 | { | |||
299 | const dw_tag_t tag = die.Tag(); | |||
300 | ||||
301 | bool add_type = false; | |||
302 | ||||
303 | switch (tag) | |||
304 | { | |||
305 | case DW_TAG_array_type: add_type = (type_mask & eTypeClassArray ) != 0; break; | |||
306 | case DW_TAG_unspecified_type: | |||
307 | case DW_TAG_base_type: add_type = (type_mask & eTypeClassBuiltin ) != 0; break; | |||
308 | case DW_TAG_class_type: add_type = (type_mask & eTypeClassClass ) != 0; break; | |||
309 | case DW_TAG_structure_type: add_type = (type_mask & eTypeClassStruct ) != 0; break; | |||
310 | case DW_TAG_union_type: add_type = (type_mask & eTypeClassUnion ) != 0; break; | |||
311 | case DW_TAG_enumeration_type: add_type = (type_mask & eTypeClassEnumeration ) != 0; break; | |||
312 | case DW_TAG_subroutine_type: | |||
313 | case DW_TAG_subprogram: | |||
314 | case DW_TAG_inlined_subroutine: add_type = (type_mask & eTypeClassFunction ) != 0; break; | |||
315 | case DW_TAG_pointer_type: add_type = (type_mask & eTypeClassPointer ) != 0; break; | |||
316 | case DW_TAG_rvalue_reference_type: | |||
317 | case DW_TAG_reference_type: add_type = (type_mask & eTypeClassReference ) != 0; break; | |||
318 | case DW_TAG_typedef: add_type = (type_mask & eTypeClassTypedef ) != 0; break; | |||
319 | case DW_TAG_ptr_to_member_type: add_type = (type_mask & eTypeClassMemberPointer ) != 0; break; | |||
320 | } | |||
321 | ||||
322 | if (add_type) | |||
323 | { | |||
324 | const bool assert_not_being_parsed = true; | |||
325 | Type *type = ResolveTypeUID (die, assert_not_being_parsed); | |||
326 | if (type) | |||
327 | { | |||
328 | if (type_set.find(type) == type_set.end()) | |||
329 | type_set.insert(type); | |||
330 | } | |||
331 | } | |||
332 | } | |||
333 | ||||
334 | for (DWARFDIE child_die = die.GetFirstChild(); | |||
335 | child_die.IsValid(); | |||
336 | child_die = child_die.GetSibling()) | |||
337 | { | |||
338 | GetTypes (child_die, min_die_offset, max_die_offset, type_mask, type_set); | |||
339 | } | |||
340 | } | |||
341 | } | |||
342 | ||||
343 | size_t | |||
344 | SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope, | |||
345 | uint32_t type_mask, | |||
346 | TypeList &type_list) | |||
347 | ||||
348 | { | |||
349 | TypeSet type_set; | |||
350 | ||||
351 | CompileUnit *comp_unit = NULL__null; | |||
352 | DWARFCompileUnit* dwarf_cu = NULL__null; | |||
353 | if (sc_scope) | |||
354 | comp_unit = sc_scope->CalculateSymbolContextCompileUnit(); | |||
355 | ||||
356 | if (comp_unit) | |||
357 | { | |||
358 | dwarf_cu = GetDWARFCompileUnit(comp_unit); | |||
359 | if (dwarf_cu == 0) | |||
360 | return 0; | |||
361 | GetTypes (dwarf_cu->DIE(), | |||
362 | dwarf_cu->GetOffset(), | |||
363 | dwarf_cu->GetNextCompileUnitOffset(), | |||
364 | type_mask, | |||
365 | type_set); | |||
366 | } | |||
367 | else | |||
368 | { | |||
369 | DWARFDebugInfo* info = DebugInfo(); | |||
370 | if (info) | |||
371 | { | |||
372 | const size_t num_cus = info->GetNumCompileUnits(); | |||
373 | for (size_t cu_idx=0; cu_idx<num_cus; ++cu_idx) | |||
374 | { | |||
375 | dwarf_cu = info->GetCompileUnitAtIndex(cu_idx); | |||
376 | if (dwarf_cu) | |||
377 | { | |||
378 | GetTypes (dwarf_cu->DIE(), | |||
379 | 0, | |||
380 | UINT32_MAX(4294967295U), | |||
381 | type_mask, | |||
382 | type_set); | |||
383 | } | |||
384 | } | |||
385 | } | |||
386 | } | |||
387 | ||||
388 | std::set<CompilerType> compiler_type_set; | |||
389 | size_t num_types_added = 0; | |||
390 | for (Type *type : type_set) | |||
391 | { | |||
392 | CompilerType compiler_type = type->GetForwardCompilerType (); | |||
393 | if (compiler_type_set.find(compiler_type) == compiler_type_set.end()) | |||
394 | { | |||
395 | compiler_type_set.insert(compiler_type); | |||
396 | type_list.Insert (type->shared_from_this()); | |||
397 | ++num_types_added; | |||
398 | } | |||
399 | } | |||
400 | return num_types_added; | |||
401 | } | |||
402 | ||||
403 | ||||
404 | //---------------------------------------------------------------------- | |||
405 | // Gets the first parent that is a lexical block, function or inlined | |||
406 | // subroutine, or compile unit. | |||
407 | //---------------------------------------------------------------------- | |||
408 | DWARFDIE | |||
409 | SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) | |||
410 | { | |||
411 | DWARFDIE die; | |||
412 | for (die = child_die.GetParent(); die; die = die.GetParent()) | |||
413 | { | |||
414 | dw_tag_t tag = die.Tag(); | |||
415 | ||||
416 | switch (tag) | |||
417 | { | |||
418 | case DW_TAG_compile_unit: | |||
419 | case DW_TAG_subprogram: | |||
420 | case DW_TAG_inlined_subroutine: | |||
421 | case DW_TAG_lexical_block: | |||
422 | return die; | |||
423 | } | |||
424 | } | |||
425 | return DWARFDIE(); | |||
426 | } | |||
427 | ||||
428 | ||||
429 | SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) : | |||
430 | SymbolFile (objfile), | |||
431 | UserID (0), // Used by SymbolFileDWARFDebugMap to when this class parses .o files to contain the .o file index/ID | |||
432 | m_debug_map_module_wp (), | |||
433 | m_debug_map_symfile (NULL__null), | |||
434 | m_data_debug_abbrev (), | |||
435 | m_data_debug_aranges (), | |||
436 | m_data_debug_frame (), | |||
437 | m_data_debug_info (), | |||
438 | m_data_debug_line (), | |||
439 | m_data_debug_loc (), | |||
440 | m_data_debug_ranges (), | |||
441 | m_data_debug_str (), | |||
442 | m_data_apple_names (), | |||
443 | m_data_apple_types (), | |||
444 | m_data_apple_namespaces (), | |||
445 | m_abbr(), | |||
446 | m_info(), | |||
447 | m_line(), | |||
448 | m_apple_names_ap (), | |||
449 | m_apple_types_ap (), | |||
450 | m_apple_namespaces_ap (), | |||
451 | m_apple_objc_ap (), | |||
452 | m_function_basename_index(), | |||
453 | m_function_fullname_index(), | |||
454 | m_function_method_index(), | |||
455 | m_function_selector_index(), | |||
456 | m_objc_class_selectors_index(), | |||
457 | m_global_index(), | |||
458 | m_type_index(), | |||
459 | m_namespace_index(), | |||
460 | m_indexed (false), | |||
461 | m_using_apple_tables (false), | |||
462 | m_fetched_external_modules (false), | |||
463 | m_supports_DW_AT_APPLE_objc_complete_type (eLazyBoolCalculate), | |||
464 | m_ranges(), | |||
465 | m_unique_ast_type_map () | |||
466 | { | |||
467 | } | |||
468 | ||||
469 | SymbolFileDWARF::~SymbolFileDWARF() | |||
470 | { | |||
471 | } | |||
472 | ||||
473 | static const ConstString & | |||
474 | GetDWARFMachOSegmentName () | |||
475 | { | |||
476 | static ConstString g_dwarf_section_name ("__DWARF"); | |||
477 | return g_dwarf_section_name; | |||
478 | } | |||
479 | ||||
480 | UniqueDWARFASTTypeMap & | |||
481 | SymbolFileDWARF::GetUniqueDWARFASTTypeMap () | |||
482 | { | |||
483 | if (GetDebugMapSymfile ()) | |||
484 | return m_debug_map_symfile->GetUniqueDWARFASTTypeMap (); | |||
485 | return m_unique_ast_type_map; | |||
486 | } | |||
487 | ||||
488 | TypeSystem * | |||
489 | SymbolFileDWARF::GetTypeSystemForLanguage (LanguageType language) | |||
490 | { | |||
491 | SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile (); | |||
492 | TypeSystem *type_system; | |||
493 | if (debug_map_symfile) | |||
494 | { | |||
495 | type_system = debug_map_symfile->GetTypeSystemForLanguage(language); | |||
496 | } | |||
497 | else | |||
498 | { | |||
499 | type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language); | |||
500 | if (type_system) | |||
501 | type_system->SetSymbolFile(this); | |||
502 | } | |||
503 | return type_system; | |||
504 | } | |||
505 | ||||
506 | void | |||
507 | SymbolFileDWARF::InitializeObject() | |||
508 | { | |||
509 | ModuleSP module_sp (m_obj_file->GetModule()); | |||
510 | if (module_sp) | |||
511 | { | |||
512 | const SectionList *section_list = module_sp->GetSectionList(); | |||
513 | const Section* section = section_list->FindSectionByName(GetDWARFMachOSegmentName ()).get(); | |||
514 | ||||
515 | // Memory map the DWARF mach-o segment so we have everything mmap'ed | |||
516 | // to keep our heap memory usage down. | |||
517 | if (section) | |||
518 | m_obj_file->MemoryMapSectionData(section, m_dwarf_data); | |||
519 | } | |||
520 | ||||
521 | get_apple_names_data(); | |||
522 | if (m_data_apple_names.m_data.GetByteSize() > 0) | |||
523 | { | |||
524 | m_apple_names_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_names.m_data, | |||
525 | get_debug_str_data(), | |||
526 | ".apple_names")); | |||
527 | if (m_apple_names_ap->IsValid()) | |||
528 | m_using_apple_tables = true; | |||
529 | else | |||
530 | m_apple_names_ap.reset(); | |||
531 | } | |||
532 | get_apple_types_data(); | |||
533 | if (m_data_apple_types.m_data.GetByteSize() > 0) | |||
534 | { | |||
535 | m_apple_types_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_types.m_data, | |||
536 | get_debug_str_data(), | |||
537 | ".apple_types")); | |||
538 | if (m_apple_types_ap->IsValid()) | |||
539 | m_using_apple_tables = true; | |||
540 | else | |||
541 | m_apple_types_ap.reset(); | |||
542 | } | |||
543 | ||||
544 | get_apple_namespaces_data(); | |||
545 | if (m_data_apple_namespaces.m_data.GetByteSize() > 0) | |||
546 | { | |||
547 | m_apple_namespaces_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_namespaces.m_data, | |||
548 | get_debug_str_data(), | |||
549 | ".apple_namespaces")); | |||
550 | if (m_apple_namespaces_ap->IsValid()) | |||
551 | m_using_apple_tables = true; | |||
552 | else | |||
553 | m_apple_namespaces_ap.reset(); | |||
554 | } | |||
555 | ||||
556 | get_apple_objc_data(); | |||
557 | if (m_data_apple_objc.m_data.GetByteSize() > 0) | |||
558 | { | |||
559 | m_apple_objc_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_objc.m_data, | |||
560 | get_debug_str_data(), | |||
561 | ".apple_objc")); | |||
562 | if (m_apple_objc_ap->IsValid()) | |||
563 | m_using_apple_tables = true; | |||
564 | else | |||
565 | m_apple_objc_ap.reset(); | |||
566 | } | |||
567 | } | |||
568 | ||||
569 | bool | |||
570 | SymbolFileDWARF::SupportedVersion(uint16_t version) | |||
571 | { | |||
572 | return version == 2 || version == 3 || version == 4; | |||
573 | } | |||
574 | ||||
575 | uint32_t | |||
576 | SymbolFileDWARF::CalculateAbilities () | |||
577 | { | |||
578 | uint32_t abilities = 0; | |||
579 | if (m_obj_file != NULL__null) | |||
580 | { | |||
581 | const Section* section = NULL__null; | |||
582 | const SectionList *section_list = m_obj_file->GetSectionList(); | |||
583 | if (section_list == NULL__null) | |||
584 | return 0; | |||
585 | ||||
586 | uint64_t debug_abbrev_file_size = 0; | |||
587 | uint64_t debug_info_file_size = 0; | |||
588 | uint64_t debug_line_file_size = 0; | |||
589 | ||||
590 | section = section_list->FindSectionByName(GetDWARFMachOSegmentName ()).get(); | |||
591 | ||||
592 | if (section) | |||
593 | section_list = §ion->GetChildren (); | |||
594 | ||||
595 | section = section_list->FindSectionByType (eSectionTypeDWARFDebugInfo, true).get(); | |||
596 | if (section != NULL__null) | |||
597 | { | |||
598 | debug_info_file_size = section->GetFileSize(); | |||
599 | ||||
600 | section = section_list->FindSectionByType (eSectionTypeDWARFDebugAbbrev, true).get(); | |||
601 | if (section) | |||
602 | debug_abbrev_file_size = section->GetFileSize(); | |||
603 | ||||
604 | section = section_list->FindSectionByType (eSectionTypeDWARFDebugLine, true).get(); | |||
605 | if (section) | |||
606 | debug_line_file_size = section->GetFileSize(); | |||
607 | } | |||
608 | else | |||
609 | { | |||
610 | const char *symfile_dir_cstr = m_obj_file->GetFileSpec().GetDirectory().GetCString(); | |||
611 | if (symfile_dir_cstr) | |||
612 | { | |||
613 | if (strcasestr(symfile_dir_cstr, ".dsym")) | |||
614 | { | |||
615 | if (m_obj_file->GetType() == ObjectFile::eTypeDebugInfo) | |||
616 | { | |||
617 | // We have a dSYM file that didn't have a any debug info. | |||
618 | // If the string table has a size of 1, then it was made from | |||
619 | // an executable with no debug info, or from an executable that | |||
620 | // was stripped. | |||
621 | section = section_list->FindSectionByType (eSectionTypeDWARFDebugStr, true).get(); | |||
622 | if (section && section->GetFileSize() == 1) | |||
623 | { | |||
624 | m_obj_file->GetModule()->ReportWarning ("empty dSYM file detected, dSYM was created with an executable with no debug info."); | |||
625 | } | |||
626 | } | |||
627 | } | |||
628 | } | |||
629 | } | |||
630 | ||||
631 | if (debug_abbrev_file_size > 0 && debug_info_file_size > 0) | |||
632 | abilities |= CompileUnits | Functions | Blocks | GlobalVariables | LocalVariables | VariableTypes; | |||
633 | ||||
634 | if (debug_line_file_size > 0) | |||
635 | abilities |= LineTables; | |||
636 | } | |||
637 | return abilities; | |||
638 | } | |||
639 | ||||
640 | const DWARFDataExtractor& | |||
641 | SymbolFileDWARF::GetCachedSectionData (lldb::SectionType sect_type, DWARFDataSegment& data_segment) | |||
642 | { | |||
643 | std::call_once(data_segment.m_flag, | |||
644 | &SymbolFileDWARF::LoadSectionData, | |||
645 | this, | |||
646 | sect_type, | |||
647 | std::ref(data_segment.m_data)); | |||
648 | return data_segment.m_data; | |||
649 | } | |||
650 | ||||
651 | void | |||
652 | SymbolFileDWARF::LoadSectionData (lldb::SectionType sect_type, DWARFDataExtractor& data) | |||
653 | { | |||
654 | ModuleSP module_sp (m_obj_file->GetModule()); | |||
655 | const SectionList *section_list = module_sp->GetSectionList(); | |||
656 | if (section_list) | |||
657 | { | |||
658 | SectionSP section_sp (section_list->FindSectionByType(sect_type, true)); | |||
659 | if (section_sp) | |||
660 | { | |||
661 | // See if we memory mapped the DWARF segment? | |||
662 | if (m_dwarf_data.GetByteSize()) | |||
663 | { | |||
664 | data.SetData(m_dwarf_data, section_sp->GetOffset(), section_sp->GetFileSize()); | |||
665 | } | |||
666 | else | |||
667 | { | |||
668 | if (m_obj_file->ReadSectionData(section_sp.get(), data) == 0) | |||
669 | data.Clear(); | |||
670 | } | |||
671 | } | |||
672 | } | |||
673 | } | |||
674 | ||||
675 | const DWARFDataExtractor& | |||
676 | SymbolFileDWARF::get_debug_abbrev_data() | |||
677 | { | |||
678 | return GetCachedSectionData (eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev); | |||
679 | } | |||
680 | ||||
681 | const DWARFDataExtractor& | |||
682 | SymbolFileDWARF::get_debug_addr_data() | |||
683 | { | |||
684 | return GetCachedSectionData (eSectionTypeDWARFDebugAddr, m_data_debug_addr); | |||
685 | } | |||
686 | ||||
687 | const DWARFDataExtractor& | |||
688 | SymbolFileDWARF::get_debug_aranges_data() | |||
689 | { | |||
690 | return GetCachedSectionData (eSectionTypeDWARFDebugAranges, m_data_debug_aranges); | |||
691 | } | |||
692 | ||||
693 | const DWARFDataExtractor& | |||
694 | SymbolFileDWARF::get_debug_frame_data() | |||
695 | { | |||
696 | return GetCachedSectionData (eSectionTypeDWARFDebugFrame, m_data_debug_frame); | |||
697 | } | |||
698 | ||||
699 | const DWARFDataExtractor& | |||
700 | SymbolFileDWARF::get_debug_info_data() | |||
701 | { | |||
702 | return GetCachedSectionData (eSectionTypeDWARFDebugInfo, m_data_debug_info); | |||
703 | } | |||
704 | ||||
705 | const DWARFDataExtractor& | |||
706 | SymbolFileDWARF::get_debug_line_data() | |||
707 | { | |||
708 | return GetCachedSectionData (eSectionTypeDWARFDebugLine, m_data_debug_line); | |||
709 | } | |||
710 | ||||
711 | const DWARFDataExtractor& | |||
712 | SymbolFileDWARF::get_debug_loc_data() | |||
713 | { | |||
714 | return GetCachedSectionData (eSectionTypeDWARFDebugLoc, m_data_debug_loc); | |||
715 | } | |||
716 | ||||
717 | const DWARFDataExtractor& | |||
718 | SymbolFileDWARF::get_debug_ranges_data() | |||
719 | { | |||
720 | return GetCachedSectionData (eSectionTypeDWARFDebugRanges, m_data_debug_ranges); | |||
721 | } | |||
722 | ||||
723 | const DWARFDataExtractor& | |||
724 | SymbolFileDWARF::get_debug_str_data() | |||
725 | { | |||
726 | return GetCachedSectionData (eSectionTypeDWARFDebugStr, m_data_debug_str); | |||
727 | } | |||
728 | ||||
729 | const DWARFDataExtractor& | |||
730 | SymbolFileDWARF::get_debug_str_offsets_data() | |||
731 | { | |||
732 | return GetCachedSectionData (eSectionTypeDWARFDebugStrOffsets, m_data_debug_str_offsets); | |||
733 | } | |||
734 | ||||
735 | const DWARFDataExtractor& | |||
736 | SymbolFileDWARF::get_apple_names_data() | |||
737 | { | |||
738 | return GetCachedSectionData (eSectionTypeDWARFAppleNames, m_data_apple_names); | |||
739 | } | |||
740 | ||||
741 | const DWARFDataExtractor& | |||
742 | SymbolFileDWARF::get_apple_types_data() | |||
743 | { | |||
744 | return GetCachedSectionData (eSectionTypeDWARFAppleTypes, m_data_apple_types); | |||
745 | } | |||
746 | ||||
747 | const DWARFDataExtractor& | |||
748 | SymbolFileDWARF::get_apple_namespaces_data() | |||
749 | { | |||
750 | return GetCachedSectionData (eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces); | |||
751 | } | |||
752 | ||||
753 | const DWARFDataExtractor& | |||
754 | SymbolFileDWARF::get_apple_objc_data() | |||
755 | { | |||
756 | return GetCachedSectionData (eSectionTypeDWARFAppleObjC, m_data_apple_objc); | |||
757 | } | |||
758 | ||||
759 | ||||
760 | DWARFDebugAbbrev* | |||
761 | SymbolFileDWARF::DebugAbbrev() | |||
762 | { | |||
763 | if (m_abbr.get() == NULL__null) | |||
764 | { | |||
765 | const DWARFDataExtractor &debug_abbrev_data = get_debug_abbrev_data(); | |||
766 | if (debug_abbrev_data.GetByteSize() > 0) | |||
767 | { | |||
768 | m_abbr.reset(new DWARFDebugAbbrev()); | |||
769 | if (m_abbr.get()) | |||
770 | m_abbr->Parse(debug_abbrev_data); | |||
771 | } | |||
772 | } | |||
773 | return m_abbr.get(); | |||
774 | } | |||
775 | ||||
776 | const DWARFDebugAbbrev* | |||
777 | SymbolFileDWARF::DebugAbbrev() const | |||
778 | { | |||
779 | return m_abbr.get(); | |||
780 | } | |||
781 | ||||
782 | ||||
783 | DWARFDebugInfo* | |||
784 | SymbolFileDWARF::DebugInfo() | |||
785 | { | |||
786 | if (m_info.get() == NULL__null) | |||
787 | { | |||
788 | Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", | |||
789 | __PRETTY_FUNCTION__, static_cast<void*>(this)); | |||
790 | if (get_debug_info_data().GetByteSize() > 0) | |||
791 | { | |||
792 | m_info.reset(new DWARFDebugInfo()); | |||
793 | if (m_info.get()) | |||
794 | { | |||
795 | m_info->SetDwarfData(this); | |||
796 | } | |||
797 | } | |||
798 | } | |||
799 | return m_info.get(); | |||
800 | } | |||
801 | ||||
802 | const DWARFDebugInfo* | |||
803 | SymbolFileDWARF::DebugInfo() const | |||
804 | { | |||
805 | return m_info.get(); | |||
806 | } | |||
807 | ||||
808 | DWARFCompileUnit* | |||
809 | SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) | |||
810 | { | |||
811 | if (!comp_unit) | |||
812 | return nullptr; | |||
813 | ||||
814 | DWARFDebugInfo* info = DebugInfo(); | |||
815 | if (info) | |||
816 | { | |||
817 | if (GetDebugMapSymfile ()) | |||
818 | { | |||
819 | // The debug map symbol file made the compile units for this DWARF | |||
820 | // file which is .o file with DWARF in it, and we should have | |||
821 | // only 1 compile unit which is at offset zero in the DWARF. | |||
822 | // TODO: modify to support LTO .o files where each .o file might | |||
823 | // have multiple DW_TAG_compile_unit tags. | |||
824 | ||||
825 | DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(0); | |||
826 | if (dwarf_cu && dwarf_cu->GetUserData() == NULL__null) | |||
827 | dwarf_cu->SetUserData(comp_unit); | |||
828 | return dwarf_cu; | |||
829 | } | |||
830 | else | |||
831 | { | |||
832 | // Just a normal DWARF file whose user ID for the compile unit is | |||
833 | // the DWARF offset itself | |||
834 | ||||
835 | DWARFCompileUnit *dwarf_cu = info->GetCompileUnit((dw_offset_t)comp_unit->GetID()); | |||
836 | if (dwarf_cu && dwarf_cu->GetUserData() == NULL__null) | |||
837 | dwarf_cu->SetUserData(comp_unit); | |||
838 | return dwarf_cu; | |||
839 | ||||
840 | } | |||
841 | } | |||
842 | return NULL__null; | |||
843 | } | |||
844 | ||||
845 | ||||
846 | DWARFDebugRanges* | |||
847 | SymbolFileDWARF::DebugRanges() | |||
848 | { | |||
849 | if (m_ranges.get() == NULL__null) | |||
850 | { | |||
851 | Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", | |||
852 | __PRETTY_FUNCTION__, static_cast<void*>(this)); | |||
853 | if (get_debug_ranges_data().GetByteSize() > 0) | |||
854 | { | |||
855 | m_ranges.reset(new DWARFDebugRanges()); | |||
856 | if (m_ranges.get()) | |||
857 | m_ranges->Extract(this); | |||
858 | } | |||
859 | } | |||
860 | return m_ranges.get(); | |||
861 | } | |||
862 | ||||
863 | const DWARFDebugRanges* | |||
864 | SymbolFileDWARF::DebugRanges() const | |||
865 | { | |||
866 | return m_ranges.get(); | |||
867 | } | |||
868 | ||||
869 | lldb::CompUnitSP | |||
870 | SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) | |||
871 | { | |||
872 | CompUnitSP cu_sp; | |||
873 | if (dwarf_cu) | |||
874 | { | |||
875 | CompileUnit *comp_unit = (CompileUnit*)dwarf_cu->GetUserData(); | |||
876 | if (comp_unit) | |||
877 | { | |||
878 | // We already parsed this compile unit, had out a shared pointer to it | |||
879 | cu_sp = comp_unit->shared_from_this(); | |||
880 | } | |||
881 | else | |||
882 | { | |||
883 | if (dwarf_cu->GetSymbolFileDWARF() != this) | |||
884 | { | |||
885 | return dwarf_cu->GetSymbolFileDWARF()->ParseCompileUnit(dwarf_cu, cu_idx); | |||
886 | } | |||
887 | else if (GetDebugMapSymfile ()) | |||
888 | { | |||
889 | // Let the debug map create the compile unit | |||
890 | cu_sp = m_debug_map_symfile->GetCompileUnit(this); | |||
891 | dwarf_cu->SetUserData(cu_sp.get()); | |||
892 | } | |||
893 | else | |||
894 | { | |||
895 | ModuleSP module_sp (m_obj_file->GetModule()); | |||
896 | if (module_sp) | |||
897 | { | |||
898 | const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly (); | |||
899 | if (cu_die) | |||
900 | { | |||
901 | FileSpec cu_file_spec{cu_die.GetName(), false}; | |||
902 | if (cu_file_spec) | |||
903 | { | |||
904 | // If we have a full path to the compile unit, we don't need to resolve | |||
905 | // the file. This can be expensive e.g. when the source files are NFS mounted. | |||
906 | if (cu_file_spec.IsRelative()) | |||
907 | { | |||
908 | const char *cu_comp_dir{cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr)}; | |||
909 | cu_file_spec.PrependPathComponent(resolveCompDir(cu_comp_dir)); | |||
910 | } | |||
911 | ||||
912 | std::string remapped_file; | |||
913 | if (module_sp->RemapSourceFile(cu_file_spec.GetCString(), remapped_file)) | |||
914 | cu_file_spec.SetFile(remapped_file, false); | |||
915 | } | |||
916 | ||||
917 | LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0)); | |||
918 | ||||
919 | bool is_optimized = dwarf_cu->GetIsOptimized (); | |||
920 | cu_sp.reset(new CompileUnit (module_sp, | |||
921 | dwarf_cu, | |||
922 | cu_file_spec, | |||
923 | dwarf_cu->GetID(), | |||
924 | cu_language, | |||
925 | is_optimized)); | |||
926 | if (cu_sp) | |||
927 | { | |||
928 | // If we just created a compile unit with an invalid file spec, try and get the | |||
929 | // first entry in the supports files from the line table as that should be the | |||
930 | // compile unit. | |||
931 | if (!cu_file_spec) | |||
932 | { | |||
933 | cu_file_spec = cu_sp->GetSupportFiles().GetFileSpecAtIndex(1); | |||
934 | if (cu_file_spec) | |||
935 | { | |||
936 | (FileSpec &)(*cu_sp) = cu_file_spec; | |||
937 | // Also fix the invalid file spec which was copied from the compile unit. | |||
938 | cu_sp->GetSupportFiles().Replace(0, cu_file_spec); | |||
939 | } | |||
940 | } | |||
941 | ||||
942 | dwarf_cu->SetUserData(cu_sp.get()); | |||
943 | ||||
944 | // Figure out the compile unit index if we weren't given one | |||
945 | if (cu_idx == UINT32_MAX(4294967295U)) | |||
946 | DebugInfo()->GetCompileUnit(dwarf_cu->GetOffset(), &cu_idx); | |||
947 | ||||
948 | m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(cu_idx, cu_sp); | |||
949 | } | |||
950 | } | |||
951 | } | |||
952 | } | |||
953 | } | |||
954 | } | |||
955 | return cu_sp; | |||
956 | } | |||
957 | ||||
958 | uint32_t | |||
959 | SymbolFileDWARF::GetNumCompileUnits() | |||
960 | { | |||
961 | DWARFDebugInfo* info = DebugInfo(); | |||
962 | if (info) | |||
963 | return info->GetNumCompileUnits(); | |||
964 | return 0; | |||
965 | } | |||
966 | ||||
967 | CompUnitSP | |||
968 | SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) | |||
969 | { | |||
970 | CompUnitSP cu_sp; | |||
971 | DWARFDebugInfo* info = DebugInfo(); | |||
972 | if (info) | |||
973 | { | |||
974 | DWARFCompileUnit* dwarf_cu = info->GetCompileUnitAtIndex(cu_idx); | |||
975 | if (dwarf_cu) | |||
976 | cu_sp = ParseCompileUnit(dwarf_cu, cu_idx); | |||
977 | } | |||
978 | return cu_sp; | |||
979 | } | |||
980 | ||||
981 | Function * | |||
982 | SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, const DWARFDIE &die) | |||
983 | { | |||
984 | if (die.IsValid()) | |||
985 | { | |||
986 | TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); | |||
987 | ||||
988 | if (type_system) | |||
989 | { | |||
990 | DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); | |||
991 | if (dwarf_ast) | |||
992 | return dwarf_ast->ParseFunctionFromDWARF(sc, die); | |||
993 | } | |||
994 | } | |||
995 | return nullptr; | |||
996 | } | |||
997 | ||||
998 | bool | |||
999 | SymbolFileDWARF::FixupAddress (Address &addr) | |||
1000 | { | |||
1001 | SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile (); | |||
1002 | if (debug_map_symfile) | |||
1003 | { | |||
1004 | return debug_map_symfile->LinkOSOAddress(addr); | |||
1005 | } | |||
1006 | // This is a normal DWARF file, no address fixups need to happen | |||
1007 | return true; | |||
1008 | } | |||
1009 | lldb::LanguageType | |||
1010 | SymbolFileDWARF::ParseCompileUnitLanguage (const SymbolContext& sc) | |||
1011 | { | |||
1012 | assert (sc.comp_unit)((sc.comp_unit) ? static_cast<void> (0) : __assert_fail ("sc.comp_unit", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 1012, __PRETTY_FUNCTION__)); | |||
1013 | DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); | |||
1014 | if (dwarf_cu) | |||
1015 | return dwarf_cu->GetLanguageType(); | |||
1016 | else | |||
1017 | return eLanguageTypeUnknown; | |||
1018 | } | |||
1019 | ||||
1020 | size_t | |||
1021 | SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc) | |||
1022 | { | |||
1023 | assert (sc.comp_unit)((sc.comp_unit) ? static_cast<void> (0) : __assert_fail ("sc.comp_unit", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 1023, __PRETTY_FUNCTION__)); | |||
1024 | size_t functions_added = 0; | |||
1025 | DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); | |||
1026 | if (dwarf_cu) | |||
1027 | { | |||
1028 | DWARFDIECollection function_dies; | |||
1029 | const size_t num_functions = dwarf_cu->AppendDIEsWithTag (DW_TAG_subprogram, function_dies); | |||
1030 | size_t func_idx; | |||
1031 | for (func_idx = 0; func_idx < num_functions; ++func_idx) | |||
1032 | { | |||
1033 | DWARFDIE die = function_dies.GetDIEAtIndex(func_idx); | |||
1034 | if (sc.comp_unit->FindFunctionByUID (die.GetID()).get() == NULL__null) | |||
1035 | { | |||
1036 | if (ParseCompileUnitFunction(sc, die)) | |||
1037 | ++functions_added; | |||
1038 | } | |||
1039 | } | |||
1040 | //FixupTypes(); | |||
1041 | } | |||
1042 | return functions_added; | |||
1043 | } | |||
1044 | ||||
1045 | bool | |||
1046 | SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files) | |||
1047 | { | |||
1048 | assert (sc.comp_unit)((sc.comp_unit) ? static_cast<void> (0) : __assert_fail ("sc.comp_unit", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 1048, __PRETTY_FUNCTION__)); | |||
1049 | DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); | |||
1050 | if (dwarf_cu) | |||
1051 | { | |||
1052 | const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly(); | |||
1053 | ||||
1054 | if (cu_die) | |||
1055 | { | |||
1056 | const char * cu_comp_dir = resolveCompDir(cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr)); | |||
1057 | ||||
1058 | const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET(~(dw_offset_t)0)); | |||
1059 | ||||
1060 | // All file indexes in DWARF are one based and a file of index zero is | |||
1061 | // supposed to be the compile unit itself. | |||
1062 | support_files.Append (*sc.comp_unit); | |||
1063 | ||||
1064 | return DWARFDebugLine::ParseSupportFiles(sc.comp_unit->GetModule(), get_debug_line_data(), cu_comp_dir, stmt_list, support_files); | |||
1065 | } | |||
1066 | } | |||
1067 | return false; | |||
1068 | } | |||
1069 | ||||
1070 | bool | |||
1071 | SymbolFileDWARF::ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules) | |||
1072 | { | |||
1073 | assert (sc.comp_unit)((sc.comp_unit) ? static_cast<void> (0) : __assert_fail ("sc.comp_unit", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 1073, __PRETTY_FUNCTION__)); | |||
1074 | DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); | |||
1075 | if (dwarf_cu) | |||
| ||||
1076 | { | |||
1077 | if (ClangModulesDeclVendor::LanguageSupportsClangModules(sc.comp_unit->GetLanguage())) | |||
1078 | { | |||
1079 | UpdateExternalModuleListIfNeeded(); | |||
1080 | for (const std::pair<uint64_t, const ClangModuleInfo> &external_type_module : m_external_type_modules) | |||
1081 | { | |||
1082 | imported_modules.push_back(external_type_module.second.m_name); | |||
| ||||
1083 | } | |||
1084 | } | |||
1085 | } | |||
1086 | return false; | |||
1087 | } | |||
1088 | ||||
1089 | struct ParseDWARFLineTableCallbackInfo | |||
1090 | { | |||
1091 | LineTable* line_table; | |||
1092 | std::unique_ptr<LineSequence> sequence_ap; | |||
1093 | lldb::addr_t addr_mask; | |||
1094 | }; | |||
1095 | ||||
1096 | //---------------------------------------------------------------------- | |||
1097 | // ParseStatementTableCallback | |||
1098 | //---------------------------------------------------------------------- | |||
1099 | static void | |||
1100 | ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& state, void* userData) | |||
1101 | { | |||
1102 | if (state.row == DWARFDebugLine::State::StartParsingLineTable) | |||
1103 | { | |||
1104 | // Just started parsing the line table | |||
1105 | } | |||
1106 | else if (state.row == DWARFDebugLine::State::DoneParsingLineTable) | |||
1107 | { | |||
1108 | // Done parsing line table, nothing to do for the cleanup | |||
1109 | } | |||
1110 | else | |||
1111 | { | |||
1112 | ParseDWARFLineTableCallbackInfo* info = (ParseDWARFLineTableCallbackInfo*)userData; | |||
1113 | LineTable* line_table = info->line_table; | |||
1114 | ||||
1115 | // If this is our first time here, we need to create a | |||
1116 | // sequence container. | |||
1117 | if (!info->sequence_ap.get()) | |||
1118 | { | |||
1119 | info->sequence_ap.reset(line_table->CreateLineSequenceContainer()); | |||
1120 | assert(info->sequence_ap.get())((info->sequence_ap.get()) ? static_cast<void> (0) : __assert_fail ("info->sequence_ap.get()", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 1120, __PRETTY_FUNCTION__)); | |||
1121 | } | |||
1122 | line_table->AppendLineEntryToSequence (info->sequence_ap.get(), | |||
1123 | state.address & info->addr_mask, | |||
1124 | state.line, | |||
1125 | state.column, | |||
1126 | state.file, | |||
1127 | state.is_stmt, | |||
1128 | state.basic_block, | |||
1129 | state.prologue_end, | |||
1130 | state.epilogue_begin, | |||
1131 | state.end_sequence); | |||
1132 | if (state.end_sequence) | |||
1133 | { | |||
1134 | // First, put the current sequence into the line table. | |||
1135 | line_table->InsertSequence(info->sequence_ap.get()); | |||
1136 | // Then, empty it to prepare for the next sequence. | |||
1137 | info->sequence_ap->Clear(); | |||
1138 | } | |||
1139 | } | |||
1140 | } | |||
1141 | ||||
1142 | bool | |||
1143 | SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc) | |||
1144 | { | |||
1145 | assert (sc.comp_unit)((sc.comp_unit) ? static_cast<void> (0) : __assert_fail ("sc.comp_unit", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 1145, __PRETTY_FUNCTION__)); | |||
1146 | if (sc.comp_unit->GetLineTable() != NULL__null) | |||
1147 | return true; | |||
1148 | ||||
1149 | DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); | |||
1150 | if (dwarf_cu) | |||
1151 | { | |||
1152 | const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly(); | |||
1153 | if (dwarf_cu_die) | |||
1154 | { | |||
1155 | const dw_offset_t cu_line_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET(~(dw_offset_t)0)); | |||
1156 | if (cu_line_offset != DW_INVALID_OFFSET(~(dw_offset_t)0)) | |||
1157 | { | |||
1158 | std::unique_ptr<LineTable> line_table_ap(new LineTable(sc.comp_unit)); | |||
1159 | if (line_table_ap.get()) | |||
1160 | { | |||
1161 | ParseDWARFLineTableCallbackInfo info; | |||
1162 | info.line_table = line_table_ap.get(); | |||
1163 | ||||
1164 | /* | |||
1165 | * MIPS: | |||
1166 | * The SymbolContext may not have a valid target, thus we may not be able | |||
1167 | * to call Address::GetOpcodeLoadAddress() which would clear the bit #0 | |||
1168 | * for MIPS. Use ArchSpec to clear the bit #0. | |||
1169 | */ | |||
1170 | ArchSpec arch; | |||
1171 | GetObjectFile()->GetArchitecture(arch); | |||
1172 | switch (arch.GetMachine()) | |||
1173 | { | |||
1174 | case llvm::Triple::mips: | |||
1175 | case llvm::Triple::mipsel: | |||
1176 | case llvm::Triple::mips64: | |||
1177 | case llvm::Triple::mips64el: | |||
1178 | info.addr_mask = ~((lldb::addr_t)1); | |||
1179 | break; | |||
1180 | default: | |||
1181 | info.addr_mask = ~((lldb::addr_t)0); | |||
1182 | break; | |||
1183 | } | |||
1184 | ||||
1185 | lldb::offset_t offset = cu_line_offset; | |||
1186 | DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, ParseDWARFLineTableCallback, &info); | |||
1187 | if (m_debug_map_symfile) | |||
1188 | { | |||
1189 | // We have an object file that has a line table with addresses | |||
1190 | // that are not linked. We need to link the line table and convert | |||
1191 | // the addresses that are relative to the .o file into addresses | |||
1192 | // for the main executable. | |||
1193 | sc.comp_unit->SetLineTable (m_debug_map_symfile->LinkOSOLineTable (this, line_table_ap.get())); | |||
1194 | } | |||
1195 | else | |||
1196 | { | |||
1197 | sc.comp_unit->SetLineTable(line_table_ap.release()); | |||
1198 | return true; | |||
1199 | } | |||
1200 | } | |||
1201 | } | |||
1202 | } | |||
1203 | } | |||
1204 | return false; | |||
1205 | } | |||
1206 | ||||
1207 | size_t | |||
1208 | SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext& sc, | |||
1209 | Block *parent_block, | |||
1210 | const DWARFDIE &orig_die, | |||
1211 | addr_t subprogram_low_pc, | |||
1212 | uint32_t depth) | |||
1213 | { | |||
1214 | size_t blocks_added = 0; | |||
1215 | DWARFDIE die = orig_die; | |||
1216 | while (die) | |||
1217 | { | |||
1218 | dw_tag_t tag = die.Tag(); | |||
1219 | ||||
1220 | switch (tag) | |||
1221 | { | |||
1222 | case DW_TAG_inlined_subroutine: | |||
1223 | case DW_TAG_subprogram: | |||
1224 | case DW_TAG_lexical_block: | |||
1225 | { | |||
1226 | Block *block = NULL__null; | |||
1227 | if (tag == DW_TAG_subprogram) | |||
1228 | { | |||
1229 | // Skip any DW_TAG_subprogram DIEs that are inside | |||
1230 | // of a normal or inlined functions. These will be | |||
1231 | // parsed on their own as separate entities. | |||
1232 | ||||
1233 | if (depth > 0) | |||
1234 | break; | |||
1235 | ||||
1236 | block = parent_block; | |||
1237 | } | |||
1238 | else | |||
1239 | { | |||
1240 | BlockSP block_sp(new Block (die.GetID())); | |||
1241 | parent_block->AddChild(block_sp); | |||
1242 | block = block_sp.get(); | |||
1243 | } | |||
1244 | DWARFRangeList ranges; | |||
1245 | const char *name = NULL__null; | |||
1246 | const char *mangled_name = NULL__null; | |||
1247 | ||||
1248 | int decl_file = 0; | |||
1249 | int decl_line = 0; | |||
1250 | int decl_column = 0; | |||
1251 | int call_file = 0; | |||
1252 | int call_line = 0; | |||
1253 | int call_column = 0; | |||
1254 | if (die.GetDIENamesAndRanges (name, | |||
1255 | mangled_name, | |||
1256 | ranges, | |||
1257 | decl_file, decl_line, decl_column, | |||
1258 | call_file, call_line, call_column, nullptr)) | |||
1259 | { | |||
1260 | if (tag == DW_TAG_subprogram) | |||
1261 | { | |||
1262 | assert (subprogram_low_pc == LLDB_INVALID_ADDRESS)((subprogram_low_pc == (18446744073709551615UL)) ? static_cast <void> (0) : __assert_fail ("subprogram_low_pc == (18446744073709551615UL)" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 1262, __PRETTY_FUNCTION__)); | |||
1263 | subprogram_low_pc = ranges.GetMinRangeBase(0); | |||
1264 | } | |||
1265 | else if (tag == DW_TAG_inlined_subroutine) | |||
1266 | { | |||
1267 | // We get called here for inlined subroutines in two ways. | |||
1268 | // The first time is when we are making the Function object | |||
1269 | // for this inlined concrete instance. Since we're creating a top level block at | |||
1270 | // here, the subprogram_low_pc will be LLDB_INVALID_ADDRESS. So we need to | |||
1271 | // adjust the containing address. | |||
1272 | // The second time is when we are parsing the blocks inside the function that contains | |||
1273 | // the inlined concrete instance. Since these will be blocks inside the containing "real" | |||
1274 | // function the offset will be for that function. | |||
1275 | if (subprogram_low_pc == LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
1276 | { | |||
1277 | subprogram_low_pc = ranges.GetMinRangeBase(0); | |||
1278 | } | |||
1279 | } | |||
1280 | ||||
1281 | const size_t num_ranges = ranges.GetSize(); | |||
1282 | for (size_t i = 0; i<num_ranges; ++i) | |||
1283 | { | |||
1284 | const DWARFRangeList::Entry &range = ranges.GetEntryRef (i); | |||
1285 | const addr_t range_base = range.GetRangeBase(); | |||
1286 | if (range_base >= subprogram_low_pc) | |||
1287 | block->AddRange(Block::Range (range_base - subprogram_low_pc, range.GetByteSize())); | |||
1288 | else | |||
1289 | { | |||
1290 | GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64"l" "x" ": adding range [0x%" PRIx64"l" "x" "-0x%" PRIx64"l" "x" ") which has a base that is less than the function's low PC 0x%" PRIx64"l" "x" ". Please file a bug and attach the file at the start of this error message", | |||
1291 | block->GetID(), | |||
1292 | range_base, | |||
1293 | range.GetRangeEnd(), | |||
1294 | subprogram_low_pc); | |||
1295 | } | |||
1296 | } | |||
1297 | block->FinalizeRanges (); | |||
1298 | ||||
1299 | if (tag != DW_TAG_subprogram && (name != NULL__null || mangled_name != NULL__null)) | |||
1300 | { | |||
1301 | std::unique_ptr<Declaration> decl_ap; | |||
1302 | if (decl_file != 0 || decl_line != 0 || decl_column != 0) | |||
1303 | decl_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), | |||
1304 | decl_line, decl_column)); | |||
1305 | ||||
1306 | std::unique_ptr<Declaration> call_ap; | |||
1307 | if (call_file != 0 || call_line != 0 || call_column != 0) | |||
1308 | call_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(call_file), | |||
1309 | call_line, call_column)); | |||
1310 | ||||
1311 | block->SetInlinedFunctionInfo (name, mangled_name, decl_ap.get(), call_ap.get()); | |||
1312 | } | |||
1313 | ||||
1314 | ++blocks_added; | |||
1315 | ||||
1316 | if (die.HasChildren()) | |||
1317 | { | |||
1318 | blocks_added += ParseFunctionBlocks (sc, | |||
1319 | block, | |||
1320 | die.GetFirstChild(), | |||
1321 | subprogram_low_pc, | |||
1322 | depth + 1); | |||
1323 | } | |||
1324 | } | |||
1325 | } | |||
1326 | break; | |||
1327 | default: | |||
1328 | break; | |||
1329 | } | |||
1330 | ||||
1331 | // Only parse siblings of the block if we are not at depth zero. A depth | |||
1332 | // of zero indicates we are currently parsing the top level | |||
1333 | // DW_TAG_subprogram DIE | |||
1334 | ||||
1335 | if (depth == 0) | |||
1336 | die.Clear(); | |||
1337 | else | |||
1338 | die = die.GetSibling(); | |||
1339 | } | |||
1340 | return blocks_added; | |||
1341 | } | |||
1342 | ||||
1343 | bool | |||
1344 | SymbolFileDWARF::ClassOrStructIsVirtual (const DWARFDIE &parent_die) | |||
1345 | { | |||
1346 | if (parent_die) | |||
1347 | { | |||
1348 | for (DWARFDIE die = parent_die.GetFirstChild(); die; die = die.GetSibling()) | |||
1349 | { | |||
1350 | dw_tag_t tag = die.Tag(); | |||
1351 | bool check_virtuality = false; | |||
1352 | switch (tag) | |||
1353 | { | |||
1354 | case DW_TAG_inheritance: | |||
1355 | case DW_TAG_subprogram: | |||
1356 | check_virtuality = true; | |||
1357 | break; | |||
1358 | default: | |||
1359 | break; | |||
1360 | } | |||
1361 | if (check_virtuality) | |||
1362 | { | |||
1363 | if (die.GetAttributeValueAsUnsigned(DW_AT_virtuality, 0) != 0) | |||
1364 | return true; | |||
1365 | } | |||
1366 | } | |||
1367 | } | |||
1368 | return false; | |||
1369 | } | |||
1370 | ||||
1371 | void | |||
1372 | SymbolFileDWARF::ParseDeclsForContext (CompilerDeclContext decl_ctx) | |||
1373 | { | |||
1374 | TypeSystem *type_system = decl_ctx.GetTypeSystem(); | |||
1375 | DWARFASTParser *ast_parser = type_system->GetDWARFParser(); | |||
1376 | std::vector<DWARFDIE> decl_ctx_die_list = ast_parser->GetDIEForDeclContext(decl_ctx); | |||
1377 | ||||
1378 | for (DWARFDIE decl_ctx_die : decl_ctx_die_list) | |||
1379 | for (DWARFDIE decl = decl_ctx_die.GetFirstChild(); decl; decl = decl.GetSibling()) | |||
1380 | ast_parser->GetDeclForUIDFromDWARF(decl); | |||
1381 | } | |||
1382 | ||||
1383 | CompilerDecl | |||
1384 | SymbolFileDWARF::GetDeclForUID (lldb::user_id_t type_uid) | |||
1385 | { | |||
1386 | if (UserIDMatches(type_uid)) | |||
1387 | { | |||
1388 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
1389 | if (debug_info) | |||
1390 | { | |||
1391 | DWARFDIE die = debug_info->GetDIE(DIERef(type_uid)); | |||
1392 | if (die) | |||
1393 | { | |||
1394 | DWARFASTParser *dwarf_ast = die.GetDWARFParser(); | |||
1395 | if (dwarf_ast) | |||
1396 | return dwarf_ast->GetDeclForUIDFromDWARF(die); | |||
1397 | } | |||
1398 | } | |||
1399 | } | |||
1400 | return CompilerDecl(); | |||
1401 | } | |||
1402 | ||||
1403 | CompilerDeclContext | |||
1404 | SymbolFileDWARF::GetDeclContextForUID (lldb::user_id_t type_uid) | |||
1405 | { | |||
1406 | if (UserIDMatches(type_uid)) | |||
1407 | { | |||
1408 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
1409 | if (debug_info) | |||
1410 | { | |||
1411 | DWARFDIE die = debug_info->GetDIE(DIERef(type_uid)); | |||
1412 | if (die) | |||
1413 | { | |||
1414 | DWARFASTParser *dwarf_ast = die.GetDWARFParser(); | |||
1415 | if (dwarf_ast) | |||
1416 | return dwarf_ast->GetDeclContextForUIDFromDWARF(die); | |||
1417 | } | |||
1418 | } | |||
1419 | } | |||
1420 | return CompilerDeclContext(); | |||
1421 | } | |||
1422 | ||||
1423 | CompilerDeclContext | |||
1424 | SymbolFileDWARF::GetDeclContextContainingUID (lldb::user_id_t type_uid) | |||
1425 | { | |||
1426 | if (UserIDMatches(type_uid)) | |||
1427 | { | |||
1428 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
1429 | if (debug_info) | |||
1430 | { | |||
1431 | DWARFDIE die = debug_info->GetDIE(DIERef(type_uid)); | |||
1432 | if (die) | |||
1433 | { | |||
1434 | DWARFASTParser *dwarf_ast = die.GetDWARFParser(); | |||
1435 | if (dwarf_ast) | |||
1436 | return dwarf_ast->GetDeclContextContainingUIDFromDWARF(die); | |||
1437 | } | |||
1438 | } | |||
1439 | } | |||
1440 | return CompilerDeclContext(); | |||
1441 | } | |||
1442 | ||||
1443 | ||||
1444 | Type* | |||
1445 | SymbolFileDWARF::ResolveTypeUID (lldb::user_id_t type_uid) | |||
1446 | { | |||
1447 | if (UserIDMatches(type_uid)) | |||
1448 | { | |||
1449 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
1450 | if (debug_info) | |||
1451 | { | |||
1452 | DWARFDIE type_die = debug_info->GetDIE (DIERef(type_uid)); | |||
1453 | if (type_die) | |||
1454 | { | |||
1455 | const bool assert_not_being_parsed = true; | |||
1456 | return ResolveTypeUID (type_die, assert_not_being_parsed); | |||
1457 | } | |||
1458 | } | |||
1459 | } | |||
1460 | return NULL__null; | |||
1461 | } | |||
1462 | ||||
1463 | Type* | |||
1464 | SymbolFileDWARF::ResolveTypeUID (const DWARFDIE &die, bool assert_not_being_parsed) | |||
1465 | { | |||
1466 | if (die) | |||
1467 | { | |||
1468 | Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO(1u << 1))); | |||
1469 | if (log) | |||
1470 | GetObjectFile()->GetModule()->LogMessage (log, | |||
1471 | "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s'", | |||
1472 | die.GetOffset(), | |||
1473 | die.GetTagAsCString(), | |||
1474 | die.GetName()); | |||
1475 | ||||
1476 | // We might be coming in in the middle of a type tree (a class | |||
1477 | // withing a class, an enum within a class), so parse any needed | |||
1478 | // parent DIEs before we get to this one... | |||
1479 | DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE (die); | |||
1480 | if (decl_ctx_die) | |||
1481 | { | |||
1482 | if (log) | |||
1483 | { | |||
1484 | switch (decl_ctx_die.Tag()) | |||
1485 | { | |||
1486 | case DW_TAG_structure_type: | |||
1487 | case DW_TAG_union_type: | |||
1488 | case DW_TAG_class_type: | |||
1489 | { | |||
1490 | // Get the type, which could be a forward declaration | |||
1491 | if (log) | |||
1492 | GetObjectFile()->GetModule()->LogMessage (log, | |||
1493 | "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent forward type for 0x%8.8x", | |||
1494 | die.GetOffset(), | |||
1495 | die.GetTagAsCString(), | |||
1496 | die.GetName(), | |||
1497 | decl_ctx_die.GetOffset()); | |||
1498 | } | |||
1499 | break; | |||
1500 | ||||
1501 | default: | |||
1502 | break; | |||
1503 | } | |||
1504 | } | |||
1505 | } | |||
1506 | return ResolveType (die); | |||
1507 | } | |||
1508 | return NULL__null; | |||
1509 | } | |||
1510 | ||||
1511 | // This function is used when SymbolFileDWARFDebugMap owns a bunch of | |||
1512 | // SymbolFileDWARF objects to detect if this DWARF file is the one that | |||
1513 | // can resolve a compiler_type. | |||
1514 | bool | |||
1515 | SymbolFileDWARF::HasForwardDeclForClangType (const CompilerType &compiler_type) | |||
1516 | { | |||
1517 | CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type); | |||
1518 | return GetForwardDeclClangTypeToDie().count (compiler_type_no_qualifiers.GetOpaqueQualType()); | |||
1519 | } | |||
1520 | ||||
1521 | ||||
1522 | bool | |||
1523 | SymbolFileDWARF::CompleteType (CompilerType &compiler_type) | |||
1524 | { | |||
1525 | // We have a struct/union/class/enum that needs to be fully resolved. | |||
1526 | CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type); | |||
1527 | auto die_it = GetForwardDeclClangTypeToDie().find (compiler_type_no_qualifiers.GetOpaqueQualType()); | |||
1528 | if (die_it == GetForwardDeclClangTypeToDie().end()) | |||
1529 | { | |||
1530 | // We have already resolved this type... | |||
1531 | return true; | |||
1532 | } | |||
1533 | ||||
1534 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
1535 | DWARFDIE dwarf_die = debug_info->GetDIE(die_it->getSecond()); | |||
1536 | ||||
1537 | assert(UserIDMatches(die_it->getSecond().GetUID()) && "CompleteType called on the wrong SymbolFile")((UserIDMatches(die_it->getSecond().GetUID()) && "CompleteType called on the wrong SymbolFile" ) ? static_cast<void> (0) : __assert_fail ("UserIDMatches(die_it->getSecond().GetUID()) && \"CompleteType called on the wrong SymbolFile\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 1537, __PRETTY_FUNCTION__)); | |||
1538 | ||||
1539 | // Once we start resolving this type, remove it from the forward declaration | |||
1540 | // map in case anyone child members or other types require this type to get resolved. | |||
1541 | // The type will get resolved when all of the calls to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition | |||
1542 | // are done. | |||
1543 | GetForwardDeclClangTypeToDie().erase (die_it); | |||
1544 | ||||
1545 | Type *type = GetDIEToType().lookup (dwarf_die.GetDIE()); | |||
1546 | ||||
1547 | Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO(1u << 1)|DWARF_LOG_TYPE_COMPLETION(1u << 7))); | |||
1548 | if (log) | |||
1549 | GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log, | |||
1550 | "0x%8.8" PRIx64"l" "x" ": %s '%s' resolving forward declaration...", | |||
1551 | dwarf_die.GetID(), | |||
1552 | dwarf_die.GetTagAsCString(), | |||
1553 | type->GetName().AsCString()); | |||
1554 | assert (compiler_type)((compiler_type) ? static_cast<void> (0) : __assert_fail ("compiler_type", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 1554, __PRETTY_FUNCTION__)); | |||
1555 | DWARFASTParser *dwarf_ast = dwarf_die.GetDWARFParser(); | |||
1556 | if (dwarf_ast) | |||
1557 | return dwarf_ast->CompleteTypeFromDWARF (dwarf_die, type, compiler_type); | |||
1558 | return false; | |||
1559 | } | |||
1560 | ||||
1561 | Type* | |||
1562 | SymbolFileDWARF::ResolveType (const DWARFDIE &die, bool assert_not_being_parsed, bool resolve_function_context) | |||
1563 | { | |||
1564 | if (die) | |||
1565 | { | |||
1566 | Type *type = GetDIEToType().lookup (die.GetDIE()); | |||
1567 | ||||
1568 | if (type == NULL__null) | |||
1569 | type = GetTypeForDIE (die, resolve_function_context).get(); | |||
1570 | ||||
1571 | if (assert_not_being_parsed) | |||
1572 | { | |||
1573 | if (type != DIE_IS_BEING_PARSED((lldb_private::Type*)1)) | |||
1574 | return type; | |||
1575 | ||||
1576 | GetObjectFile()->GetModule()->ReportError ("Parsing a die that is being parsed die: 0x%8.8x: %s %s", | |||
1577 | die.GetOffset(), | |||
1578 | die.GetTagAsCString(), | |||
1579 | die.GetName()); | |||
1580 | ||||
1581 | } | |||
1582 | else | |||
1583 | return type; | |||
1584 | } | |||
1585 | return nullptr; | |||
1586 | } | |||
1587 | ||||
1588 | CompileUnit* | |||
1589 | SymbolFileDWARF::GetCompUnitForDWARFCompUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) | |||
1590 | { | |||
1591 | // Check if the symbol vendor already knows about this compile unit? | |||
1592 | if (dwarf_cu->GetUserData() == NULL__null) | |||
1593 | { | |||
1594 | // The symbol vendor doesn't know about this compile unit, we | |||
1595 | // need to parse and add it to the symbol vendor object. | |||
1596 | return ParseCompileUnit(dwarf_cu, cu_idx).get(); | |||
1597 | } | |||
1598 | return (CompileUnit*)dwarf_cu->GetUserData(); | |||
1599 | } | |||
1600 | ||||
1601 | size_t | |||
1602 | SymbolFileDWARF::GetObjCMethodDIEOffsets (ConstString class_name, DIEArray &method_die_offsets) | |||
1603 | { | |||
1604 | method_die_offsets.clear(); | |||
1605 | if (m_using_apple_tables) | |||
1606 | { | |||
1607 | if (m_apple_objc_ap.get()) | |||
1608 | m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets); | |||
1609 | } | |||
1610 | else | |||
1611 | { | |||
1612 | if (!m_indexed) | |||
1613 | Index (); | |||
1614 | ||||
1615 | m_objc_class_selectors_index.Find (class_name, method_die_offsets); | |||
1616 | } | |||
1617 | return method_die_offsets.size(); | |||
1618 | } | |||
1619 | ||||
1620 | bool | |||
1621 | SymbolFileDWARF::GetFunction (const DWARFDIE &die, SymbolContext& sc) | |||
1622 | { | |||
1623 | sc.Clear(false); | |||
1624 | ||||
1625 | if (die) | |||
1626 | { | |||
1627 | // Check if the symbol vendor already knows about this compile unit? | |||
1628 | sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX(4294967295U)); | |||
1629 | ||||
1630 | sc.function = sc.comp_unit->FindFunctionByUID (die.GetID()).get(); | |||
1631 | if (sc.function == NULL__null) | |||
1632 | sc.function = ParseCompileUnitFunction(sc, die); | |||
1633 | ||||
1634 | if (sc.function) | |||
1635 | { | |||
1636 | sc.module_sp = sc.function->CalculateSymbolContextModule(); | |||
1637 | return true; | |||
1638 | } | |||
1639 | } | |||
1640 | ||||
1641 | return false; | |||
1642 | } | |||
1643 | ||||
1644 | void | |||
1645 | SymbolFileDWARF::UpdateExternalModuleListIfNeeded() | |||
1646 | { | |||
1647 | if (m_fetched_external_modules) | |||
1648 | return; | |||
1649 | m_fetched_external_modules = true; | |||
1650 | ||||
1651 | DWARFDebugInfo * debug_info = DebugInfo(); | |||
1652 | ||||
1653 | const uint32_t num_compile_units = GetNumCompileUnits(); | |||
1654 | for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) | |||
1655 | { | |||
1656 | DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); | |||
1657 | ||||
1658 | const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly(); | |||
1659 | if (die && die.HasChildren() == false) | |||
1660 | { | |||
1661 | const uint64_t name_strp = die.GetAttributeValueAsUnsigned (DW_AT_name, UINT64_MAX(18446744073709551615UL)); | |||
1662 | const uint64_t dwo_path_strp = die.GetAttributeValueAsUnsigned (DW_AT_GNU_dwo_name, UINT64_MAX(18446744073709551615UL)); | |||
1663 | ||||
1664 | if (name_strp != UINT64_MAX(18446744073709551615UL)) | |||
1665 | { | |||
1666 | if (m_external_type_modules.find(dwo_path_strp) == m_external_type_modules.end()) | |||
1667 | { | |||
1668 | const char *name = get_debug_str_data().PeekCStr(name_strp); | |||
1669 | const char *dwo_path = get_debug_str_data().PeekCStr(dwo_path_strp); | |||
1670 | if (name || dwo_path) | |||
1671 | { | |||
1672 | ModuleSP module_sp; | |||
1673 | if (dwo_path) | |||
1674 | { | |||
1675 | ModuleSpec dwo_module_spec; | |||
1676 | dwo_module_spec.GetFileSpec().SetFile(dwo_path, false); | |||
1677 | dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture(); | |||
1678 | //printf ("Loading dwo = '%s'\n", dwo_path); | |||
1679 | Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL__null, NULL__null, NULL__null); | |||
1680 | } | |||
1681 | ||||
1682 | if (dwo_path_strp != LLDB_INVALID_UID(18446744073709551615UL)) | |||
1683 | { | |||
1684 | m_external_type_modules[dwo_path_strp] = ClangModuleInfo { ConstString(name), module_sp }; | |||
1685 | } | |||
1686 | else | |||
1687 | { | |||
1688 | // This hack should be removed promptly once clang emits both. | |||
1689 | m_external_type_modules[name_strp] = ClangModuleInfo { ConstString(name), module_sp }; | |||
1690 | } | |||
1691 | } | |||
1692 | } | |||
1693 | } | |||
1694 | } | |||
1695 | } | |||
1696 | } | |||
1697 | ||||
1698 | SymbolFileDWARF::GlobalVariableMap & | |||
1699 | SymbolFileDWARF::GetGlobalAranges() | |||
1700 | { | |||
1701 | if (!m_global_aranges_ap) | |||
1702 | { | |||
1703 | m_global_aranges_ap.reset (new GlobalVariableMap()); | |||
1704 | ||||
1705 | ModuleSP module_sp = GetObjectFile()->GetModule(); | |||
1706 | if (module_sp) | |||
1707 | { | |||
1708 | const size_t num_cus = module_sp->GetNumCompileUnits(); | |||
1709 | for (size_t i = 0; i < num_cus; ++i) | |||
1710 | { | |||
1711 | CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(i); | |||
1712 | if (cu_sp) | |||
1713 | { | |||
1714 | VariableListSP globals_sp = cu_sp->GetVariableList(true); | |||
1715 | if (globals_sp) | |||
1716 | { | |||
1717 | const size_t num_globals = globals_sp->GetSize(); | |||
1718 | for (size_t g = 0; g < num_globals; ++g) | |||
1719 | { | |||
1720 | VariableSP var_sp = globals_sp->GetVariableAtIndex(g); | |||
1721 | if (var_sp && !var_sp->GetLocationIsConstantValueData()) | |||
1722 | { | |||
1723 | const DWARFExpression &location = var_sp->LocationExpression(); | |||
1724 | Value location_result; | |||
1725 | Error error; | |||
1726 | if (location.Evaluate(NULL__null, NULL__null, NULL__null, LLDB_INVALID_ADDRESS(18446744073709551615UL), NULL__null, location_result, &error)) | |||
1727 | { | |||
1728 | if (location_result.GetValueType() == Value::eValueTypeFileAddress) | |||
1729 | { | |||
1730 | lldb::addr_t file_addr = location_result.GetScalar().ULongLong(); | |||
1731 | lldb::addr_t byte_size = 1; | |||
1732 | if (var_sp->GetType()) | |||
1733 | byte_size = var_sp->GetType()->GetByteSize(); | |||
1734 | m_global_aranges_ap->Append(GlobalVariableMap::Entry(file_addr, byte_size, var_sp.get())); | |||
1735 | } | |||
1736 | } | |||
1737 | } | |||
1738 | } | |||
1739 | } | |||
1740 | } | |||
1741 | } | |||
1742 | } | |||
1743 | m_global_aranges_ap->Sort(); | |||
1744 | } | |||
1745 | return *m_global_aranges_ap; | |||
1746 | } | |||
1747 | ||||
1748 | ||||
1749 | uint32_t | |||
1750 | SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) | |||
1751 | { | |||
1752 | Timer scoped_timer(__PRETTY_FUNCTION__, | |||
1753 | "SymbolFileDWARF::ResolveSymbolContext (so_addr = { section = %p, offset = 0x%" PRIx64"l" "x" " }, resolve_scope = 0x%8.8x)", | |||
1754 | static_cast<void*>(so_addr.GetSection().get()), | |||
1755 | so_addr.GetOffset(), resolve_scope); | |||
1756 | uint32_t resolved = 0; | |||
1757 | if (resolve_scope & ( eSymbolContextCompUnit | | |||
1758 | eSymbolContextFunction | | |||
1759 | eSymbolContextBlock | | |||
1760 | eSymbolContextLineEntry | | |||
1761 | eSymbolContextVariable )) | |||
1762 | { | |||
1763 | lldb::addr_t file_vm_addr = so_addr.GetFileAddress(); | |||
1764 | ||||
1765 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
1766 | if (debug_info) | |||
1767 | { | |||
1768 | const dw_offset_t cu_offset = debug_info->GetCompileUnitAranges().FindAddress(file_vm_addr); | |||
1769 | if (cu_offset == DW_INVALID_OFFSET(~(dw_offset_t)0)) | |||
1770 | { | |||
1771 | // Global variables are not in the compile unit address ranges. The only way to | |||
1772 | // currently find global variables is to iterate over the .debug_pubnames or the | |||
1773 | // __apple_names table and find all items in there that point to DW_TAG_variable | |||
1774 | // DIEs and then find the address that matches. | |||
1775 | if (resolve_scope & eSymbolContextVariable) | |||
1776 | { | |||
1777 | GlobalVariableMap &map = GetGlobalAranges(); | |||
1778 | const GlobalVariableMap::Entry *entry = map.FindEntryThatContains(file_vm_addr); | |||
1779 | if (entry && entry->data) | |||
1780 | { | |||
1781 | Variable *variable = entry->data; | |||
1782 | SymbolContextScope *scc = variable->GetSymbolContextScope(); | |||
1783 | if (scc) | |||
1784 | { | |||
1785 | scc->CalculateSymbolContext(&sc); | |||
1786 | sc.variable = variable; | |||
1787 | } | |||
1788 | return sc.GetResolvedMask(); | |||
1789 | } | |||
1790 | } | |||
1791 | } | |||
1792 | else | |||
1793 | { | |||
1794 | uint32_t cu_idx = DW_INVALID_INDEX0xFFFFFFFFul; | |||
1795 | DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnit(cu_offset, &cu_idx); | |||
1796 | if (dwarf_cu) | |||
1797 | { | |||
1798 | sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx); | |||
1799 | if (sc.comp_unit) | |||
1800 | { | |||
1801 | resolved |= eSymbolContextCompUnit; | |||
1802 | ||||
1803 | bool force_check_line_table = false; | |||
1804 | if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) | |||
1805 | { | |||
1806 | DWARFDIE function_die = dwarf_cu->LookupAddress(file_vm_addr); | |||
1807 | DWARFDIE block_die; | |||
1808 | if (function_die) | |||
1809 | { | |||
1810 | sc.function = sc.comp_unit->FindFunctionByUID (function_die.GetID()).get(); | |||
1811 | if (sc.function == NULL__null) | |||
1812 | sc.function = ParseCompileUnitFunction(sc, function_die); | |||
1813 | ||||
1814 | if (sc.function && (resolve_scope & eSymbolContextBlock)) | |||
1815 | block_die = function_die.LookupDeepestBlock(file_vm_addr); | |||
1816 | } | |||
1817 | else | |||
1818 | { | |||
1819 | // We might have had a compile unit that had discontiguous | |||
1820 | // address ranges where the gaps are symbols that don't have | |||
1821 | // any debug info. Discontiguous compile unit address ranges | |||
1822 | // should only happen when there aren't other functions from | |||
1823 | // other compile units in these gaps. This helps keep the size | |||
1824 | // of the aranges down. | |||
1825 | force_check_line_table = true; | |||
1826 | } | |||
1827 | ||||
1828 | if (sc.function != NULL__null) | |||
1829 | { | |||
1830 | resolved |= eSymbolContextFunction; | |||
1831 | ||||
1832 | if (resolve_scope & eSymbolContextBlock) | |||
1833 | { | |||
1834 | Block& block = sc.function->GetBlock (true); | |||
1835 | ||||
1836 | if (block_die) | |||
1837 | sc.block = block.FindBlockByID (block_die.GetID()); | |||
1838 | else | |||
1839 | sc.block = block.FindBlockByID (function_die.GetID()); | |||
1840 | if (sc.block) | |||
1841 | resolved |= eSymbolContextBlock; | |||
1842 | } | |||
1843 | } | |||
1844 | } | |||
1845 | ||||
1846 | if ((resolve_scope & eSymbolContextLineEntry) || force_check_line_table) | |||
1847 | { | |||
1848 | LineTable *line_table = sc.comp_unit->GetLineTable(); | |||
1849 | if (line_table != NULL__null) | |||
1850 | { | |||
1851 | // And address that makes it into this function should be in terms | |||
1852 | // of this debug file if there is no debug map, or it will be an | |||
1853 | // address in the .o file which needs to be fixed up to be in terms | |||
1854 | // of the debug map executable. Either way, calling FixupAddress() | |||
1855 | // will work for us. | |||
1856 | Address exe_so_addr (so_addr); | |||
1857 | if (FixupAddress(exe_so_addr)) | |||
1858 | { | |||
1859 | if (line_table->FindLineEntryByAddress (exe_so_addr, sc.line_entry)) | |||
1860 | { | |||
1861 | resolved |= eSymbolContextLineEntry; | |||
1862 | } | |||
1863 | } | |||
1864 | } | |||
1865 | } | |||
1866 | ||||
1867 | if (force_check_line_table && !(resolved & eSymbolContextLineEntry)) | |||
1868 | { | |||
1869 | // We might have had a compile unit that had discontiguous | |||
1870 | // address ranges where the gaps are symbols that don't have | |||
1871 | // any debug info. Discontiguous compile unit address ranges | |||
1872 | // should only happen when there aren't other functions from | |||
1873 | // other compile units in these gaps. This helps keep the size | |||
1874 | // of the aranges down. | |||
1875 | sc.comp_unit = NULL__null; | |||
1876 | resolved &= ~eSymbolContextCompUnit; | |||
1877 | } | |||
1878 | } | |||
1879 | else | |||
1880 | { | |||
1881 | GetObjectFile()->GetModule()->ReportWarning ("0x%8.8x: compile unit %u failed to create a valid lldb_private::CompileUnit class.", | |||
1882 | cu_offset, | |||
1883 | cu_idx); | |||
1884 | } | |||
1885 | } | |||
1886 | } | |||
1887 | } | |||
1888 | } | |||
1889 | return resolved; | |||
1890 | } | |||
1891 | ||||
1892 | ||||
1893 | ||||
1894 | uint32_t | |||
1895 | SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) | |||
1896 | { | |||
1897 | const uint32_t prev_size = sc_list.GetSize(); | |||
1898 | if (resolve_scope & eSymbolContextCompUnit) | |||
1899 | { | |||
1900 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
1901 | if (debug_info) | |||
1902 | { | |||
1903 | uint32_t cu_idx; | |||
1904 | DWARFCompileUnit* dwarf_cu = NULL__null; | |||
1905 | ||||
1906 | for (cu_idx = 0; (dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx)) != NULL__null; ++cu_idx) | |||
1907 | { | |||
1908 | CompileUnit *dc_cu = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx); | |||
1909 | const bool full_match = (bool)file_spec.GetDirectory(); | |||
1910 | bool file_spec_matches_cu_file_spec = dc_cu != NULL__null && FileSpec::Equal(file_spec, *dc_cu, full_match); | |||
1911 | if (check_inlines || file_spec_matches_cu_file_spec) | |||
1912 | { | |||
1913 | SymbolContext sc (m_obj_file->GetModule()); | |||
1914 | sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx); | |||
1915 | if (sc.comp_unit) | |||
1916 | { | |||
1917 | uint32_t file_idx = UINT32_MAX(4294967295U); | |||
1918 | ||||
1919 | // If we are looking for inline functions only and we don't | |||
1920 | // find it in the support files, we are done. | |||
1921 | if (check_inlines) | |||
1922 | { | |||
1923 | file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec, true); | |||
1924 | if (file_idx == UINT32_MAX(4294967295U)) | |||
1925 | continue; | |||
1926 | } | |||
1927 | ||||
1928 | if (line != 0) | |||
1929 | { | |||
1930 | LineTable *line_table = sc.comp_unit->GetLineTable(); | |||
1931 | ||||
1932 | if (line_table != NULL__null && line != 0) | |||
1933 | { | |||
1934 | // We will have already looked up the file index if | |||
1935 | // we are searching for inline entries. | |||
1936 | if (!check_inlines) | |||
1937 | file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec, true); | |||
1938 | ||||
1939 | if (file_idx != UINT32_MAX(4294967295U)) | |||
1940 | { | |||
1941 | uint32_t found_line; | |||
1942 | uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_idx, line, false, &sc.line_entry); | |||
1943 | found_line = sc.line_entry.line; | |||
1944 | ||||
1945 | while (line_idx != UINT32_MAX(4294967295U)) | |||
1946 | { | |||
1947 | sc.function = NULL__null; | |||
1948 | sc.block = NULL__null; | |||
1949 | if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) | |||
1950 | { | |||
1951 | const lldb::addr_t file_vm_addr = sc.line_entry.range.GetBaseAddress().GetFileAddress(); | |||
1952 | if (file_vm_addr != LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
1953 | { | |||
1954 | DWARFDIE function_die = dwarf_cu->LookupAddress(file_vm_addr); | |||
1955 | DWARFDIE block_die; | |||
1956 | if (function_die) | |||
1957 | { | |||
1958 | sc.function = sc.comp_unit->FindFunctionByUID (function_die.GetID()).get(); | |||
1959 | if (sc.function == NULL__null) | |||
1960 | sc.function = ParseCompileUnitFunction(sc, function_die); | |||
1961 | ||||
1962 | if (sc.function && (resolve_scope & eSymbolContextBlock)) | |||
1963 | block_die = function_die.LookupDeepestBlock(file_vm_addr); | |||
1964 | } | |||
1965 | ||||
1966 | if (sc.function != NULL__null) | |||
1967 | { | |||
1968 | Block& block = sc.function->GetBlock (true); | |||
1969 | ||||
1970 | if (block_die) | |||
1971 | sc.block = block.FindBlockByID (block_die.GetID()); | |||
1972 | else if (function_die) | |||
1973 | sc.block = block.FindBlockByID (function_die.GetID()); | |||
1974 | } | |||
1975 | } | |||
1976 | } | |||
1977 | ||||
1978 | sc_list.Append(sc); | |||
1979 | line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_idx, found_line, true, &sc.line_entry); | |||
1980 | } | |||
1981 | } | |||
1982 | } | |||
1983 | else if (file_spec_matches_cu_file_spec && !check_inlines) | |||
1984 | { | |||
1985 | // only append the context if we aren't looking for inline call sites | |||
1986 | // by file and line and if the file spec matches that of the compile unit | |||
1987 | sc_list.Append(sc); | |||
1988 | } | |||
1989 | } | |||
1990 | else if (file_spec_matches_cu_file_spec && !check_inlines) | |||
1991 | { | |||
1992 | // only append the context if we aren't looking for inline call sites | |||
1993 | // by file and line and if the file spec matches that of the compile unit | |||
1994 | sc_list.Append(sc); | |||
1995 | } | |||
1996 | ||||
1997 | if (!check_inlines) | |||
1998 | break; | |||
1999 | } | |||
2000 | } | |||
2001 | } | |||
2002 | } | |||
2003 | } | |||
2004 | return sc_list.GetSize() - prev_size; | |||
2005 | } | |||
2006 | ||||
2007 | void | |||
2008 | SymbolFileDWARF::Index () | |||
2009 | { | |||
2010 | if (m_indexed) | |||
2011 | return; | |||
2012 | m_indexed = true; | |||
2013 | Timer scoped_timer (__PRETTY_FUNCTION__, | |||
2014 | "SymbolFileDWARF::Index (%s)", | |||
2015 | GetObjectFile()->GetFileSpec().GetFilename().AsCString("<Unknown>")); | |||
2016 | ||||
2017 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
2018 | if (debug_info) | |||
2019 | { | |||
2020 | const uint32_t num_compile_units = GetNumCompileUnits(); | |||
2021 | std::vector<NameToDIE> function_basename_index(num_compile_units); | |||
2022 | std::vector<NameToDIE> function_fullname_index(num_compile_units); | |||
2023 | std::vector<NameToDIE> function_method_index(num_compile_units); | |||
2024 | std::vector<NameToDIE> function_selector_index(num_compile_units); | |||
2025 | std::vector<NameToDIE> objc_class_selectors_index(num_compile_units); | |||
2026 | std::vector<NameToDIE> global_index(num_compile_units); | |||
2027 | std::vector<NameToDIE> type_index(num_compile_units); | |||
2028 | std::vector<NameToDIE> namespace_index(num_compile_units); | |||
2029 | ||||
2030 | auto parser_fn = [this, | |||
2031 | debug_info, | |||
2032 | &function_basename_index, | |||
2033 | &function_fullname_index, | |||
2034 | &function_method_index, | |||
2035 | &function_selector_index, | |||
2036 | &objc_class_selectors_index, | |||
2037 | &global_index, | |||
2038 | &type_index, | |||
2039 | &namespace_index](uint32_t cu_idx) | |||
2040 | { | |||
2041 | DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); | |||
2042 | bool clear_dies = dwarf_cu->ExtractDIEsIfNeeded(false) > 1; | |||
2043 | ||||
2044 | dwarf_cu->Index(function_basename_index[cu_idx], | |||
2045 | function_fullname_index[cu_idx], | |||
2046 | function_method_index[cu_idx], | |||
2047 | function_selector_index[cu_idx], | |||
2048 | objc_class_selectors_index[cu_idx], | |||
2049 | global_index[cu_idx], | |||
2050 | type_index[cu_idx], | |||
2051 | namespace_index[cu_idx]); | |||
2052 | ||||
2053 | // Keep memory down by clearing DIEs if this generate function | |||
2054 | // caused them to be parsed | |||
2055 | if (clear_dies) | |||
2056 | dwarf_cu->ClearDIEs(true); | |||
2057 | ||||
2058 | return cu_idx; | |||
2059 | }; | |||
2060 | ||||
2061 | TaskRunner<uint32_t> task_runner; | |||
2062 | for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) | |||
2063 | task_runner.AddTask(parser_fn, cu_idx); | |||
2064 | ||||
2065 | while (true) | |||
2066 | { | |||
2067 | std::future<uint32_t> f = task_runner.WaitForNextCompletedTask(); | |||
2068 | if (!f.valid()) | |||
2069 | break; | |||
2070 | uint32_t cu_idx = f.get(); | |||
2071 | ||||
2072 | m_function_basename_index.Append(function_basename_index[cu_idx]); | |||
2073 | m_function_fullname_index.Append(function_fullname_index[cu_idx]); | |||
2074 | m_function_method_index.Append(function_method_index[cu_idx]); | |||
2075 | m_function_selector_index.Append(function_selector_index[cu_idx]); | |||
2076 | m_objc_class_selectors_index.Append(objc_class_selectors_index[cu_idx]); | |||
2077 | m_global_index.Append(global_index[cu_idx]); | |||
2078 | m_type_index.Append(type_index[cu_idx]); | |||
2079 | m_namespace_index.Append(namespace_index[cu_idx]); | |||
2080 | } | |||
2081 | ||||
2082 | TaskPool::RunTasks( | |||
2083 | [&]() { m_function_basename_index.Finalize(); }, | |||
2084 | [&]() { m_function_fullname_index.Finalize(); }, | |||
2085 | [&]() { m_function_method_index.Finalize(); }, | |||
2086 | [&]() { m_function_selector_index.Finalize(); }, | |||
2087 | [&]() { m_objc_class_selectors_index.Finalize(); }, | |||
2088 | [&]() { m_global_index.Finalize(); }, | |||
2089 | [&]() { m_type_index.Finalize(); }, | |||
2090 | [&]() { m_namespace_index.Finalize(); }); | |||
2091 | ||||
2092 | #if defined (ENABLE_DEBUG_PRINTF) | |||
2093 | StreamFile s(stdoutstdout, false); | |||
2094 | s.Printf ("DWARF index for '%s':", | |||
2095 | GetObjectFile()->GetFileSpec().GetPath().c_str()); | |||
2096 | s.Printf("\nFunction basenames:\n"); m_function_basename_index.Dump (&s); | |||
2097 | s.Printf("\nFunction fullnames:\n"); m_function_fullname_index.Dump (&s); | |||
2098 | s.Printf("\nFunction methods:\n"); m_function_method_index.Dump (&s); | |||
2099 | s.Printf("\nFunction selectors:\n"); m_function_selector_index.Dump (&s); | |||
2100 | s.Printf("\nObjective C class selectors:\n"); m_objc_class_selectors_index.Dump (&s); | |||
2101 | s.Printf("\nGlobals and statics:\n"); m_global_index.Dump (&s); | |||
2102 | s.Printf("\nTypes:\n"); m_type_index.Dump (&s); | |||
2103 | s.Printf("\nNamespaces:\n") m_namespace_index.Dump (&s); | |||
2104 | #endif | |||
2105 | } | |||
2106 | } | |||
2107 | ||||
2108 | bool | |||
2109 | SymbolFileDWARF::DeclContextMatchesThisSymbolFile (const lldb_private::CompilerDeclContext *decl_ctx) | |||
2110 | { | |||
2111 | if (decl_ctx == nullptr || !decl_ctx->IsValid()) | |||
2112 | { | |||
2113 | // Invalid namespace decl which means we aren't matching only things | |||
2114 | // in this symbol file, so return true to indicate it matches this | |||
2115 | // symbol file. | |||
2116 | return true; | |||
2117 | } | |||
2118 | ||||
2119 | TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem(); | |||
2120 | TypeSystem *type_system = GetTypeSystemForLanguage(decl_ctx_type_system->GetMinimumLanguage(nullptr)); | |||
2121 | if (decl_ctx_type_system == type_system) | |||
2122 | return true; // The type systems match, return true | |||
2123 | ||||
2124 | // The namespace AST was valid, and it does not match... | |||
2125 | Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS(1u << 6))); | |||
2126 | ||||
2127 | if (log) | |||
2128 | GetObjectFile()->GetModule()->LogMessage(log, "Valid namespace does not match symbol file"); | |||
2129 | ||||
2130 | return false; | |||
2131 | } | |||
2132 | ||||
2133 | uint32_t | |||
2134 | SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, VariableList& variables) | |||
2135 | { | |||
2136 | Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS(1u << 6))); | |||
2137 | ||||
2138 | if (log) | |||
2139 | GetObjectFile()->GetModule()->LogMessage (log, | |||
2140 | "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", parent_decl_ctx=%p, append=%u, max_matches=%u, variables)", | |||
2141 | name.GetCString(), | |||
2142 | static_cast<const void*>(parent_decl_ctx), | |||
2143 | append, max_matches); | |||
2144 | ||||
2145 | if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) | |||
2146 | return 0; | |||
2147 | ||||
2148 | DWARFDebugInfo* info = DebugInfo(); | |||
2149 | if (info == NULL__null) | |||
2150 | return 0; | |||
2151 | ||||
2152 | // If we aren't appending the results to this list, then clear the list | |||
2153 | if (!append) | |||
2154 | variables.Clear(); | |||
2155 | ||||
2156 | // Remember how many variables are in the list before we search in case | |||
2157 | // we are appending the results to a variable list. | |||
2158 | const uint32_t original_size = variables.GetSize(); | |||
2159 | ||||
2160 | DIEArray die_offsets; | |||
2161 | ||||
2162 | if (m_using_apple_tables) | |||
2163 | { | |||
2164 | if (m_apple_names_ap.get()) | |||
2165 | { | |||
2166 | const char *name_cstr = name.GetCString(); | |||
2167 | llvm::StringRef basename; | |||
2168 | llvm::StringRef context; | |||
2169 | ||||
2170 | if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, basename)) | |||
2171 | basename = name_cstr; | |||
2172 | ||||
2173 | m_apple_names_ap->FindByName (basename.data(), die_offsets); | |||
2174 | } | |||
2175 | } | |||
2176 | else | |||
2177 | { | |||
2178 | // Index the DWARF if we haven't already | |||
2179 | if (!m_indexed) | |||
2180 | Index (); | |||
2181 | ||||
2182 | m_global_index.Find (name, die_offsets); | |||
2183 | } | |||
2184 | ||||
2185 | const size_t num_die_matches = die_offsets.size(); | |||
2186 | if (num_die_matches) | |||
2187 | { | |||
2188 | SymbolContext sc; | |||
2189 | sc.module_sp = m_obj_file->GetModule(); | |||
2190 | assert (sc.module_sp)((sc.module_sp) ? static_cast<void> (0) : __assert_fail ("sc.module_sp", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 2190, __PRETTY_FUNCTION__)); | |||
2191 | ||||
2192 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
2193 | bool done = false; | |||
2194 | for (size_t i=0; i<num_die_matches && !done; ++i) | |||
2195 | { | |||
2196 | const DIERef& die_ref = die_offsets[i]; | |||
2197 | DWARFDIE die = debug_info->GetDIE (die_ref); | |||
2198 | ||||
2199 | if (die) | |||
2200 | { | |||
2201 | switch (die.Tag()) | |||
2202 | { | |||
2203 | default: | |||
2204 | case DW_TAG_subprogram: | |||
2205 | case DW_TAG_inlined_subroutine: | |||
2206 | case DW_TAG_try_block: | |||
2207 | case DW_TAG_catch_block: | |||
2208 | break; | |||
2209 | ||||
2210 | case DW_TAG_variable: | |||
2211 | { | |||
2212 | sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX(4294967295U)); | |||
2213 | ||||
2214 | if (parent_decl_ctx) | |||
2215 | { | |||
2216 | DWARFASTParser *dwarf_ast = die.GetDWARFParser(); | |||
2217 | if (dwarf_ast) | |||
2218 | { | |||
2219 | CompilerDeclContext actual_parent_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF (die); | |||
2220 | if (!actual_parent_decl_ctx || actual_parent_decl_ctx != *parent_decl_ctx) | |||
2221 | continue; | |||
2222 | } | |||
2223 | } | |||
2224 | ||||
2225 | ParseVariables(sc, die, LLDB_INVALID_ADDRESS(18446744073709551615UL), false, false, &variables); | |||
2226 | ||||
2227 | if (variables.GetSize() - original_size >= max_matches) | |||
2228 | done = true; | |||
2229 | } | |||
2230 | break; | |||
2231 | } | |||
2232 | } | |||
2233 | else | |||
2234 | { | |||
2235 | if (m_using_apple_tables) | |||
2236 | { | |||
2237 | GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')\n", | |||
2238 | die_ref.die_offset, name.GetCString()); | |||
2239 | } | |||
2240 | } | |||
2241 | } | |||
2242 | } | |||
2243 | ||||
2244 | // Return the number of variable that were appended to the list | |||
2245 | const uint32_t num_matches = variables.GetSize() - original_size; | |||
2246 | if (log && num_matches > 0) | |||
2247 | { | |||
2248 | GetObjectFile()->GetModule()->LogMessage (log, | |||
2249 | "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", parent_decl_ctx=%p, append=%u, max_matches=%u, variables) => %u", | |||
2250 | name.GetCString(), | |||
2251 | static_cast<const void*>(parent_decl_ctx), | |||
2252 | append, max_matches, | |||
2253 | num_matches); | |||
2254 | } | |||
2255 | return num_matches; | |||
2256 | } | |||
2257 | ||||
2258 | uint32_t | |||
2259 | SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables) | |||
2260 | { | |||
2261 | Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS(1u << 6))); | |||
2262 | ||||
2263 | if (log) | |||
2264 | { | |||
2265 | GetObjectFile()->GetModule()->LogMessage (log, | |||
2266 | "SymbolFileDWARF::FindGlobalVariables (regex=\"%s\", append=%u, max_matches=%u, variables)", | |||
2267 | regex.GetText(), append, | |||
2268 | max_matches); | |||
2269 | } | |||
2270 | ||||
2271 | DWARFDebugInfo* info = DebugInfo(); | |||
2272 | if (info == NULL__null) | |||
2273 | return 0; | |||
2274 | ||||
2275 | // If we aren't appending the results to this list, then clear the list | |||
2276 | if (!append) | |||
2277 | variables.Clear(); | |||
2278 | ||||
2279 | // Remember how many variables are in the list before we search in case | |||
2280 | // we are appending the results to a variable list. | |||
2281 | const uint32_t original_size = variables.GetSize(); | |||
2282 | ||||
2283 | DIEArray die_offsets; | |||
2284 | ||||
2285 | if (m_using_apple_tables) | |||
2286 | { | |||
2287 | if (m_apple_names_ap.get()) | |||
2288 | { | |||
2289 | DWARFMappedHash::DIEInfoArray hash_data_array; | |||
2290 | if (m_apple_names_ap->AppendAllDIEsThatMatchingRegex (regex, hash_data_array)) | |||
2291 | DWARFMappedHash::ExtractDIEArray (hash_data_array, die_offsets); | |||
2292 | } | |||
2293 | } | |||
2294 | else | |||
2295 | { | |||
2296 | // Index the DWARF if we haven't already | |||
2297 | if (!m_indexed) | |||
2298 | Index (); | |||
2299 | ||||
2300 | m_global_index.Find (regex, die_offsets); | |||
2301 | } | |||
2302 | ||||
2303 | SymbolContext sc; | |||
2304 | sc.module_sp = m_obj_file->GetModule(); | |||
2305 | assert (sc.module_sp)((sc.module_sp) ? static_cast<void> (0) : __assert_fail ("sc.module_sp", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 2305, __PRETTY_FUNCTION__)); | |||
2306 | ||||
2307 | const size_t num_matches = die_offsets.size(); | |||
2308 | if (num_matches) | |||
2309 | { | |||
2310 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
2311 | for (size_t i=0; i<num_matches; ++i) | |||
2312 | { | |||
2313 | const DIERef& die_ref = die_offsets[i]; | |||
2314 | DWARFDIE die = debug_info->GetDIE (die_ref); | |||
2315 | ||||
2316 | if (die) | |||
2317 | { | |||
2318 | sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX(4294967295U)); | |||
2319 | ||||
2320 | ParseVariables(sc, die, LLDB_INVALID_ADDRESS(18446744073709551615UL), false, false, &variables); | |||
2321 | ||||
2322 | if (variables.GetSize() - original_size >= max_matches) | |||
2323 | break; | |||
2324 | } | |||
2325 | else | |||
2326 | { | |||
2327 | if (m_using_apple_tables) | |||
2328 | { | |||
2329 | GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for regex '%s')\n", | |||
2330 | die_ref.die_offset, regex.GetText()); | |||
2331 | } | |||
2332 | } | |||
2333 | } | |||
2334 | } | |||
2335 | ||||
2336 | // Return the number of variable that were appended to the list | |||
2337 | return variables.GetSize() - original_size; | |||
2338 | } | |||
2339 | ||||
2340 | ||||
2341 | bool | |||
2342 | SymbolFileDWARF::ResolveFunction (const DIERef& die_ref, | |||
2343 | bool include_inlines, | |||
2344 | SymbolContextList& sc_list) | |||
2345 | { | |||
2346 | DWARFDIE die = DebugInfo()->GetDIE (die_ref); | |||
2347 | return ResolveFunction (die, include_inlines, sc_list); | |||
2348 | } | |||
2349 | ||||
2350 | ||||
2351 | bool | |||
2352 | SymbolFileDWARF::ResolveFunction (const DWARFDIE &orig_die, | |||
2353 | bool include_inlines, | |||
2354 | SymbolContextList& sc_list) | |||
2355 | { | |||
2356 | SymbolContext sc; | |||
2357 | ||||
2358 | if (!orig_die) | |||
2359 | return false; | |||
2360 | ||||
2361 | // If we were passed a die that is not a function, just return false... | |||
2362 | if (!(orig_die.Tag() == DW_TAG_subprogram || (include_inlines && orig_die.Tag() == DW_TAG_inlined_subroutine))) | |||
2363 | return false; | |||
2364 | ||||
2365 | DWARFDIE die = orig_die; | |||
2366 | DWARFDIE inlined_die; | |||
2367 | if (die.Tag() == DW_TAG_inlined_subroutine) | |||
2368 | { | |||
2369 | inlined_die = die; | |||
2370 | ||||
2371 | while (1) | |||
2372 | { | |||
2373 | die = die.GetParent(); | |||
2374 | ||||
2375 | if (die) | |||
2376 | { | |||
2377 | if (die.Tag() == DW_TAG_subprogram) | |||
2378 | break; | |||
2379 | } | |||
2380 | else | |||
2381 | break; | |||
2382 | } | |||
2383 | } | |||
2384 | assert (die && die.Tag() == DW_TAG_subprogram)((die && die.Tag() == DW_TAG_subprogram) ? static_cast <void> (0) : __assert_fail ("die && die.Tag() == DW_TAG_subprogram" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 2384, __PRETTY_FUNCTION__)); | |||
2385 | if (GetFunction (die, sc)) | |||
2386 | { | |||
2387 | Address addr; | |||
2388 | // Parse all blocks if needed | |||
2389 | if (inlined_die) | |||
2390 | { | |||
2391 | Block &function_block = sc.function->GetBlock (true); | |||
2392 | sc.block = function_block.FindBlockByID (inlined_die.GetID()); | |||
2393 | if (sc.block == NULL__null) | |||
2394 | sc.block = function_block.FindBlockByID (inlined_die.GetOffset()); | |||
2395 | if (sc.block == NULL__null || sc.block->GetStartAddress (addr) == false) | |||
2396 | addr.Clear(); | |||
2397 | } | |||
2398 | else | |||
2399 | { | |||
2400 | sc.block = NULL__null; | |||
2401 | addr = sc.function->GetAddressRange().GetBaseAddress(); | |||
2402 | } | |||
2403 | ||||
2404 | if (addr.IsValid()) | |||
2405 | { | |||
2406 | sc_list.Append(sc); | |||
2407 | return true; | |||
2408 | } | |||
2409 | } | |||
2410 | ||||
2411 | return false; | |||
2412 | } | |||
2413 | ||||
2414 | void | |||
2415 | SymbolFileDWARF::FindFunctions (const ConstString &name, | |||
2416 | const NameToDIE &name_to_die, | |||
2417 | bool include_inlines, | |||
2418 | SymbolContextList& sc_list) | |||
2419 | { | |||
2420 | DIEArray die_offsets; | |||
2421 | if (name_to_die.Find (name, die_offsets)) | |||
2422 | { | |||
2423 | ParseFunctions (die_offsets, include_inlines, sc_list); | |||
2424 | } | |||
2425 | } | |||
2426 | ||||
2427 | ||||
2428 | void | |||
2429 | SymbolFileDWARF::FindFunctions (const RegularExpression ®ex, | |||
2430 | const NameToDIE &name_to_die, | |||
2431 | bool include_inlines, | |||
2432 | SymbolContextList& sc_list) | |||
2433 | { | |||
2434 | DIEArray die_offsets; | |||
2435 | if (name_to_die.Find (regex, die_offsets)) | |||
2436 | { | |||
2437 | ParseFunctions (die_offsets, include_inlines, sc_list); | |||
2438 | } | |||
2439 | } | |||
2440 | ||||
2441 | ||||
2442 | void | |||
2443 | SymbolFileDWARF::FindFunctions (const RegularExpression ®ex, | |||
2444 | const DWARFMappedHash::MemoryTable &memory_table, | |||
2445 | bool include_inlines, | |||
2446 | SymbolContextList& sc_list) | |||
2447 | { | |||
2448 | DIEArray die_offsets; | |||
2449 | DWARFMappedHash::DIEInfoArray hash_data_array; | |||
2450 | if (memory_table.AppendAllDIEsThatMatchingRegex (regex, hash_data_array)) | |||
2451 | { | |||
2452 | DWARFMappedHash::ExtractDIEArray (hash_data_array, die_offsets); | |||
2453 | ParseFunctions (die_offsets, include_inlines, sc_list); | |||
2454 | } | |||
2455 | } | |||
2456 | ||||
2457 | void | |||
2458 | SymbolFileDWARF::ParseFunctions (const DIEArray &die_offsets, | |||
2459 | bool include_inlines, | |||
2460 | SymbolContextList& sc_list) | |||
2461 | { | |||
2462 | const size_t num_matches = die_offsets.size(); | |||
2463 | if (num_matches) | |||
2464 | { | |||
2465 | for (size_t i=0; i<num_matches; ++i) | |||
2466 | ResolveFunction (die_offsets[i], include_inlines, sc_list); | |||
2467 | } | |||
2468 | } | |||
2469 | ||||
2470 | bool | |||
2471 | SymbolFileDWARF::DIEInDeclContext (const CompilerDeclContext *decl_ctx, | |||
2472 | const DWARFDIE &die) | |||
2473 | { | |||
2474 | // If we have no parent decl context to match this DIE matches, and if the parent | |||
2475 | // decl context isn't valid, we aren't trying to look for any particular decl | |||
2476 | // context so any die matches. | |||
2477 | if (decl_ctx == nullptr || !decl_ctx->IsValid()) | |||
2478 | return true; | |||
2479 | ||||
2480 | if (die) | |||
2481 | { | |||
2482 | DWARFASTParser *dwarf_ast = die.GetDWARFParser(); | |||
2483 | if (dwarf_ast) | |||
2484 | { | |||
2485 | CompilerDeclContext actual_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF (die); | |||
2486 | if (actual_decl_ctx) | |||
2487 | return actual_decl_ctx == *decl_ctx; | |||
2488 | } | |||
2489 | } | |||
2490 | return false; | |||
2491 | } | |||
2492 | ||||
2493 | uint32_t | |||
2494 | SymbolFileDWARF::FindFunctions (const ConstString &name, | |||
2495 | const CompilerDeclContext *parent_decl_ctx, | |||
2496 | uint32_t name_type_mask, | |||
2497 | bool include_inlines, | |||
2498 | bool append, | |||
2499 | SymbolContextList& sc_list) | |||
2500 | { | |||
2501 | Timer scoped_timer (__PRETTY_FUNCTION__, | |||
2502 | "SymbolFileDWARF::FindFunctions (name = '%s')", | |||
2503 | name.AsCString()); | |||
2504 | ||||
2505 | // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup() | |||
2506 | assert ((name_type_mask & eFunctionNameTypeAuto) == 0)(((name_type_mask & eFunctionNameTypeAuto) == 0) ? static_cast <void> (0) : __assert_fail ("(name_type_mask & eFunctionNameTypeAuto) == 0" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 2506, __PRETTY_FUNCTION__)); | |||
2507 | ||||
2508 | Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS(1u << 6))); | |||
2509 | ||||
2510 | if (log) | |||
2511 | { | |||
2512 | GetObjectFile()->GetModule()->LogMessage (log, | |||
2513 | "SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%x, append=%u, sc_list)", | |||
2514 | name.GetCString(), | |||
2515 | name_type_mask, | |||
2516 | append); | |||
2517 | } | |||
2518 | ||||
2519 | // If we aren't appending the results to this list, then clear the list | |||
2520 | if (!append) | |||
2521 | sc_list.Clear(); | |||
2522 | ||||
2523 | if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) | |||
2524 | return 0; | |||
2525 | ||||
2526 | // If name is empty then we won't find anything. | |||
2527 | if (name.IsEmpty()) | |||
2528 | return 0; | |||
2529 | ||||
2530 | // Remember how many sc_list are in the list before we search in case | |||
2531 | // we are appending the results to a variable list. | |||
2532 | ||||
2533 | const char *name_cstr = name.GetCString(); | |||
2534 | ||||
2535 | const uint32_t original_size = sc_list.GetSize(); | |||
2536 | ||||
2537 | DWARFDebugInfo* info = DebugInfo(); | |||
2538 | if (info == NULL__null) | |||
2539 | return 0; | |||
2540 | ||||
2541 | std::set<const DWARFDebugInfoEntry *> resolved_dies; | |||
2542 | if (m_using_apple_tables) | |||
2543 | { | |||
2544 | if (m_apple_names_ap.get()) | |||
2545 | { | |||
2546 | ||||
2547 | DIEArray die_offsets; | |||
2548 | ||||
2549 | uint32_t num_matches = 0; | |||
2550 | ||||
2551 | if (name_type_mask & eFunctionNameTypeFull) | |||
2552 | { | |||
2553 | // If they asked for the full name, match what they typed. At some point we may | |||
2554 | // want to canonicalize this (strip double spaces, etc. For now, we just add all the | |||
2555 | // dies that we find by exact match. | |||
2556 | num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets); | |||
2557 | for (uint32_t i = 0; i < num_matches; i++) | |||
2558 | { | |||
2559 | const DIERef& die_ref = die_offsets[i]; | |||
2560 | DWARFDIE die = info->GetDIE (die_ref); | |||
2561 | if (die) | |||
2562 | { | |||
2563 | if (!DIEInDeclContext(parent_decl_ctx, die)) | |||
2564 | continue; // The containing decl contexts don't match | |||
2565 | ||||
2566 | if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) | |||
2567 | { | |||
2568 | if (ResolveFunction (die, include_inlines, sc_list)) | |||
2569 | resolved_dies.insert(die.GetDIE()); | |||
2570 | } | |||
2571 | } | |||
2572 | else | |||
2573 | { | |||
2574 | GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')", | |||
2575 | die_ref.die_offset, name_cstr); | |||
2576 | } | |||
2577 | } | |||
2578 | } | |||
2579 | ||||
2580 | if (name_type_mask & eFunctionNameTypeSelector) | |||
2581 | { | |||
2582 | if (parent_decl_ctx && parent_decl_ctx->IsValid()) | |||
2583 | return 0; // no selectors in namespaces | |||
2584 | ||||
2585 | num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets); | |||
2586 | // Now make sure these are actually ObjC methods. In this case we can simply look up the name, | |||
2587 | // and if it is an ObjC method name, we're good. | |||
2588 | ||||
2589 | for (uint32_t i = 0; i < num_matches; i++) | |||
2590 | { | |||
2591 | const DIERef& die_ref = die_offsets[i]; | |||
2592 | DWARFDIE die = info->GetDIE (die_ref); | |||
2593 | if (die) | |||
2594 | { | |||
2595 | const char *die_name = die.GetName(); | |||
2596 | if (ObjCLanguage::IsPossibleObjCMethodName(die_name)) | |||
2597 | { | |||
2598 | if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) | |||
2599 | { | |||
2600 | if (ResolveFunction (die, include_inlines, sc_list)) | |||
2601 | resolved_dies.insert(die.GetDIE()); | |||
2602 | } | |||
2603 | } | |||
2604 | } | |||
2605 | else | |||
2606 | { | |||
2607 | GetObjectFile()->GetModule()->ReportError ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')", | |||
2608 | die_ref.die_offset, name_cstr); | |||
2609 | } | |||
2610 | } | |||
2611 | die_offsets.clear(); | |||
2612 | } | |||
2613 | ||||
2614 | if (((name_type_mask & eFunctionNameTypeMethod) && !parent_decl_ctx) || name_type_mask & eFunctionNameTypeBase) | |||
2615 | { | |||
2616 | // The apple_names table stores just the "base name" of C++ methods in the table. So we have to | |||
2617 | // extract the base name, look that up, and if there is any other information in the name we were | |||
2618 | // passed in we have to post-filter based on that. | |||
2619 | ||||
2620 | // FIXME: Arrange the logic above so that we don't calculate the base name twice: | |||
2621 | num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets); | |||
2622 | ||||
2623 | for (uint32_t i = 0; i < num_matches; i++) | |||
2624 | { | |||
2625 | const DIERef& die_ref = die_offsets[i]; | |||
2626 | DWARFDIE die = info->GetDIE (die_ref); | |||
2627 | if (die) | |||
2628 | { | |||
2629 | if (!DIEInDeclContext(parent_decl_ctx, die)) | |||
2630 | continue; // The containing decl contexts don't match | |||
2631 | ||||
2632 | ||||
2633 | // If we get to here, the die is good, and we should add it: | |||
2634 | if (resolved_dies.find(die.GetDIE()) == resolved_dies.end() && ResolveFunction (die, include_inlines, sc_list)) | |||
2635 | { | |||
2636 | bool keep_die = true; | |||
2637 | if ((name_type_mask & (eFunctionNameTypeBase|eFunctionNameTypeMethod)) != (eFunctionNameTypeBase|eFunctionNameTypeMethod)) | |||
2638 | { | |||
2639 | // We are looking for either basenames or methods, so we need to | |||
2640 | // trim out the ones we won't want by looking at the type | |||
2641 | SymbolContext sc; | |||
2642 | if (sc_list.GetLastContext(sc)) | |||
2643 | { | |||
2644 | if (sc.block) | |||
2645 | { | |||
2646 | // We have an inlined function | |||
2647 | } | |||
2648 | else if (sc.function) | |||
2649 | { | |||
2650 | Type *type = sc.function->GetType(); | |||
2651 | ||||
2652 | if (type) | |||
2653 | { | |||
2654 | CompilerDeclContext decl_ctx = GetDeclContextContainingUID (type->GetID()); | |||
2655 | if (decl_ctx.IsStructUnionOrClass()) | |||
2656 | { | |||
2657 | if (name_type_mask & eFunctionNameTypeBase) | |||
2658 | { | |||
2659 | sc_list.RemoveContextAtIndex(sc_list.GetSize()-1); | |||
2660 | keep_die = false; | |||
2661 | } | |||
2662 | } | |||
2663 | else | |||
2664 | { | |||
2665 | if (name_type_mask & eFunctionNameTypeMethod) | |||
2666 | { | |||
2667 | sc_list.RemoveContextAtIndex(sc_list.GetSize()-1); | |||
2668 | keep_die = false; | |||
2669 | } | |||
2670 | } | |||
2671 | } | |||
2672 | else | |||
2673 | { | |||
2674 | GetObjectFile()->GetModule()->ReportWarning ("function at die offset 0x%8.8x had no function type", | |||
2675 | die_ref.die_offset); | |||
2676 | } | |||
2677 | } | |||
2678 | } | |||
2679 | } | |||
2680 | if (keep_die) | |||
2681 | resolved_dies.insert(die.GetDIE()); | |||
2682 | } | |||
2683 | } | |||
2684 | else | |||
2685 | { | |||
2686 | GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')", | |||
2687 | die_ref.die_offset, name_cstr); | |||
2688 | } | |||
2689 | } | |||
2690 | die_offsets.clear(); | |||
2691 | } | |||
2692 | } | |||
2693 | } | |||
2694 | else | |||
2695 | { | |||
2696 | ||||
2697 | // Index the DWARF if we haven't already | |||
2698 | if (!m_indexed) | |||
2699 | Index (); | |||
2700 | ||||
2701 | if (name_type_mask & eFunctionNameTypeFull) | |||
2702 | { | |||
2703 | FindFunctions (name, m_function_fullname_index, include_inlines, sc_list); | |||
2704 | ||||
2705 | // FIXME Temporary workaround for global/anonymous namespace | |||
2706 | // functions debugging FreeBSD and Linux binaries. | |||
2707 | // If we didn't find any functions in the global namespace try | |||
2708 | // looking in the basename index but ignore any returned | |||
2709 | // functions that have a namespace but keep functions which | |||
2710 | // have an anonymous namespace | |||
2711 | // TODO: The arch in the object file isn't correct for MSVC | |||
2712 | // binaries on windows, we should find a way to make it | |||
2713 | // correct and handle those symbols as well. | |||
2714 | if (sc_list.GetSize() == original_size) | |||
2715 | { | |||
2716 | ArchSpec arch; | |||
2717 | if (!parent_decl_ctx && | |||
2718 | GetObjectFile()->GetArchitecture(arch) && | |||
2719 | (arch.GetTriple().isOSFreeBSD() || arch.GetTriple().isOSLinux() || | |||
2720 | arch.GetMachine() == llvm::Triple::hexagon)) | |||
2721 | { | |||
2722 | SymbolContextList temp_sc_list; | |||
2723 | FindFunctions (name, m_function_basename_index, include_inlines, temp_sc_list); | |||
2724 | SymbolContext sc; | |||
2725 | for (uint32_t i = 0; i < temp_sc_list.GetSize(); i++) | |||
2726 | { | |||
2727 | if (temp_sc_list.GetContextAtIndex(i, sc)) | |||
2728 | { | |||
2729 | ConstString mangled_name = sc.GetFunctionName(Mangled::ePreferMangled); | |||
2730 | ConstString demangled_name = sc.GetFunctionName(Mangled::ePreferDemangled); | |||
2731 | // Mangled names on Linux and FreeBSD are of the form: | |||
2732 | // _ZN18function_namespace13function_nameEv. | |||
2733 | if (strncmp(mangled_name.GetCString(), "_ZN", 3) || | |||
2734 | !strncmp(demangled_name.GetCString(), "(anonymous namespace)", 21)) | |||
2735 | { | |||
2736 | sc_list.Append(sc); | |||
2737 | } | |||
2738 | } | |||
2739 | } | |||
2740 | } | |||
2741 | } | |||
2742 | } | |||
2743 | DIEArray die_offsets; | |||
2744 | if (name_type_mask & eFunctionNameTypeBase) | |||
2745 | { | |||
2746 | uint32_t num_base = m_function_basename_index.Find(name, die_offsets); | |||
2747 | for (uint32_t i = 0; i < num_base; i++) | |||
2748 | { | |||
2749 | DWARFDIE die = info->GetDIE (die_offsets[i]); | |||
2750 | if (die) | |||
2751 | { | |||
2752 | if (!DIEInDeclContext(parent_decl_ctx, die)) | |||
2753 | continue; // The containing decl contexts don't match | |||
2754 | ||||
2755 | // If we get to here, the die is good, and we should add it: | |||
2756 | if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) | |||
2757 | { | |||
2758 | if (ResolveFunction (die, include_inlines, sc_list)) | |||
2759 | resolved_dies.insert(die.GetDIE()); | |||
2760 | } | |||
2761 | } | |||
2762 | } | |||
2763 | die_offsets.clear(); | |||
2764 | } | |||
2765 | ||||
2766 | if (name_type_mask & eFunctionNameTypeMethod) | |||
2767 | { | |||
2768 | if (parent_decl_ctx && parent_decl_ctx->IsValid()) | |||
2769 | return 0; // no methods in namespaces | |||
2770 | ||||
2771 | uint32_t num_base = m_function_method_index.Find(name, die_offsets); | |||
2772 | { | |||
2773 | for (uint32_t i = 0; i < num_base; i++) | |||
2774 | { | |||
2775 | DWARFDIE die = info->GetDIE (die_offsets[i]); | |||
2776 | if (die) | |||
2777 | { | |||
2778 | // If we get to here, the die is good, and we should add it: | |||
2779 | if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) | |||
2780 | { | |||
2781 | if (ResolveFunction (die, include_inlines, sc_list)) | |||
2782 | resolved_dies.insert(die.GetDIE()); | |||
2783 | } | |||
2784 | } | |||
2785 | } | |||
2786 | } | |||
2787 | die_offsets.clear(); | |||
2788 | } | |||
2789 | ||||
2790 | if ((name_type_mask & eFunctionNameTypeSelector) && (!parent_decl_ctx || !parent_decl_ctx->IsValid())) | |||
2791 | { | |||
2792 | FindFunctions (name, m_function_selector_index, include_inlines, sc_list); | |||
2793 | } | |||
2794 | ||||
2795 | } | |||
2796 | ||||
2797 | // Return the number of variable that were appended to the list | |||
2798 | const uint32_t num_matches = sc_list.GetSize() - original_size; | |||
2799 | ||||
2800 | if (log && num_matches > 0) | |||
2801 | { | |||
2802 | GetObjectFile()->GetModule()->LogMessage (log, | |||
2803 | "SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%x, include_inlines=%d, append=%u, sc_list) => %u", | |||
2804 | name.GetCString(), | |||
2805 | name_type_mask, | |||
2806 | include_inlines, | |||
2807 | append, | |||
2808 | num_matches); | |||
2809 | } | |||
2810 | return num_matches; | |||
2811 | } | |||
2812 | ||||
2813 | uint32_t | |||
2814 | SymbolFileDWARF::FindFunctions(const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list) | |||
2815 | { | |||
2816 | Timer scoped_timer (__PRETTY_FUNCTION__, | |||
2817 | "SymbolFileDWARF::FindFunctions (regex = '%s')", | |||
2818 | regex.GetText()); | |||
2819 | ||||
2820 | Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS(1u << 6))); | |||
2821 | ||||
2822 | if (log) | |||
2823 | { | |||
2824 | GetObjectFile()->GetModule()->LogMessage (log, | |||
2825 | "SymbolFileDWARF::FindFunctions (regex=\"%s\", append=%u, sc_list)", | |||
2826 | regex.GetText(), | |||
2827 | append); | |||
2828 | } | |||
2829 | ||||
2830 | ||||
2831 | // If we aren't appending the results to this list, then clear the list | |||
2832 | if (!append) | |||
2833 | sc_list.Clear(); | |||
2834 | ||||
2835 | // Remember how many sc_list are in the list before we search in case | |||
2836 | // we are appending the results to a variable list. | |||
2837 | uint32_t original_size = sc_list.GetSize(); | |||
2838 | ||||
2839 | if (m_using_apple_tables) | |||
2840 | { | |||
2841 | if (m_apple_names_ap.get()) | |||
2842 | FindFunctions (regex, *m_apple_names_ap, include_inlines, sc_list); | |||
2843 | } | |||
2844 | else | |||
2845 | { | |||
2846 | // Index the DWARF if we haven't already | |||
2847 | if (!m_indexed) | |||
2848 | Index (); | |||
2849 | ||||
2850 | FindFunctions (regex, m_function_basename_index, include_inlines, sc_list); | |||
2851 | ||||
2852 | FindFunctions (regex, m_function_fullname_index, include_inlines, sc_list); | |||
2853 | } | |||
2854 | ||||
2855 | // Return the number of variable that were appended to the list | |||
2856 | return sc_list.GetSize() - original_size; | |||
2857 | } | |||
2858 | ||||
2859 | uint32_t | |||
2860 | SymbolFileDWARF::FindTypes (const SymbolContext& sc, | |||
2861 | const ConstString &name, | |||
2862 | const CompilerDeclContext *parent_decl_ctx, | |||
2863 | bool append, | |||
2864 | uint32_t max_matches, | |||
2865 | TypeMap& types) | |||
2866 | { | |||
2867 | DWARFDebugInfo* info = DebugInfo(); | |||
2868 | if (info == NULL__null) | |||
2869 | return 0; | |||
2870 | ||||
2871 | Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS(1u << 6))); | |||
2872 | ||||
2873 | if (log) | |||
2874 | { | |||
2875 | if (parent_decl_ctx) | |||
2876 | GetObjectFile()->GetModule()->LogMessage (log, | |||
2877 | "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = %p (\"%s\"), append=%u, max_matches=%u, type_list)", | |||
2878 | name.GetCString(), | |||
2879 | static_cast<const void*>(parent_decl_ctx), | |||
2880 | parent_decl_ctx->GetName().AsCString("<NULL>"), | |||
2881 | append, max_matches); | |||
2882 | else | |||
2883 | GetObjectFile()->GetModule()->LogMessage (log, | |||
2884 | "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = NULL, append=%u, max_matches=%u, type_list)", | |||
2885 | name.GetCString(), append, | |||
2886 | max_matches); | |||
2887 | } | |||
2888 | ||||
2889 | // If we aren't appending the results to this list, then clear the list | |||
2890 | if (!append) | |||
2891 | types.Clear(); | |||
2892 | ||||
2893 | if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) | |||
2894 | return 0; | |||
2895 | ||||
2896 | DIEArray die_offsets; | |||
2897 | ||||
2898 | if (m_using_apple_tables) | |||
2899 | { | |||
2900 | if (m_apple_types_ap.get()) | |||
2901 | { | |||
2902 | const char *name_cstr = name.GetCString(); | |||
2903 | m_apple_types_ap->FindByName (name_cstr, die_offsets); | |||
2904 | } | |||
2905 | } | |||
2906 | else | |||
2907 | { | |||
2908 | if (!m_indexed) | |||
2909 | Index (); | |||
2910 | ||||
2911 | m_type_index.Find (name, die_offsets); | |||
2912 | } | |||
2913 | ||||
2914 | const size_t num_die_matches = die_offsets.size(); | |||
2915 | ||||
2916 | if (num_die_matches) | |||
2917 | { | |||
2918 | const uint32_t initial_types_size = types.GetSize(); | |||
2919 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
2920 | for (size_t i=0; i<num_die_matches; ++i) | |||
2921 | { | |||
2922 | const DIERef& die_ref = die_offsets[i]; | |||
2923 | DWARFDIE die = debug_info->GetDIE (die_ref); | |||
2924 | ||||
2925 | if (die) | |||
2926 | { | |||
2927 | if (!DIEInDeclContext(parent_decl_ctx, die)) | |||
2928 | continue; // The containing decl contexts don't match | |||
2929 | ||||
2930 | Type *matching_type = ResolveType (die, true, true); | |||
2931 | if (matching_type) | |||
2932 | { | |||
2933 | // We found a type pointer, now find the shared pointer form our type list | |||
2934 | types.InsertUnique (matching_type->shared_from_this()); | |||
2935 | if (types.GetSize() >= max_matches) | |||
2936 | break; | |||
2937 | } | |||
2938 | } | |||
2939 | else | |||
2940 | { | |||
2941 | if (m_using_apple_tables) | |||
2942 | { | |||
2943 | GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", | |||
2944 | die_ref.die_offset, name.GetCString()); | |||
2945 | } | |||
2946 | } | |||
2947 | ||||
2948 | } | |||
2949 | const uint32_t num_matches = types.GetSize() - initial_types_size; | |||
2950 | if (log && num_matches) | |||
2951 | { | |||
2952 | if (parent_decl_ctx) | |||
2953 | { | |||
2954 | GetObjectFile()->GetModule()->LogMessage (log, | |||
2955 | "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = %p (\"%s\"), append=%u, max_matches=%u, type_list) => %u", | |||
2956 | name.GetCString(), | |||
2957 | static_cast<const void*>(parent_decl_ctx), | |||
2958 | parent_decl_ctx->GetName().AsCString("<NULL>"), | |||
2959 | append, max_matches, | |||
2960 | num_matches); | |||
2961 | } | |||
2962 | else | |||
2963 | { | |||
2964 | GetObjectFile()->GetModule()->LogMessage (log, | |||
2965 | "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = NULL, append=%u, max_matches=%u, type_list) => %u", | |||
2966 | name.GetCString(), | |||
2967 | append, max_matches, | |||
2968 | num_matches); | |||
2969 | } | |||
2970 | } | |||
2971 | return num_matches; | |||
2972 | } | |||
2973 | return 0; | |||
2974 | } | |||
2975 | ||||
2976 | ||||
2977 | CompilerDeclContext | |||
2978 | SymbolFileDWARF::FindNamespace (const SymbolContext& sc, | |||
2979 | const ConstString &name, | |||
2980 | const CompilerDeclContext *parent_decl_ctx) | |||
2981 | { | |||
2982 | Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS(1u << 6))); | |||
2983 | ||||
2984 | if (log) | |||
2985 | { | |||
2986 | GetObjectFile()->GetModule()->LogMessage (log, | |||
2987 | "SymbolFileDWARF::FindNamespace (sc, name=\"%s\")", | |||
2988 | name.GetCString()); | |||
2989 | } | |||
2990 | ||||
2991 | CompilerDeclContext namespace_decl_ctx; | |||
2992 | ||||
2993 | if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) | |||
2994 | return namespace_decl_ctx; | |||
2995 | ||||
2996 | ||||
2997 | DWARFDebugInfo* info = DebugInfo(); | |||
2998 | if (info) | |||
2999 | { | |||
3000 | DIEArray die_offsets; | |||
3001 | ||||
3002 | // Index if we already haven't to make sure the compile units | |||
3003 | // get indexed and make their global DIE index list | |||
3004 | if (m_using_apple_tables) | |||
3005 | { | |||
3006 | if (m_apple_namespaces_ap.get()) | |||
3007 | { | |||
3008 | const char *name_cstr = name.GetCString(); | |||
3009 | m_apple_namespaces_ap->FindByName (name_cstr, die_offsets); | |||
3010 | } | |||
3011 | } | |||
3012 | else | |||
3013 | { | |||
3014 | if (!m_indexed) | |||
3015 | Index (); | |||
3016 | ||||
3017 | m_namespace_index.Find (name, die_offsets); | |||
3018 | } | |||
3019 | ||||
3020 | const size_t num_matches = die_offsets.size(); | |||
3021 | if (num_matches) | |||
3022 | { | |||
3023 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
3024 | for (size_t i=0; i<num_matches; ++i) | |||
3025 | { | |||
3026 | const DIERef& die_ref = die_offsets[i]; | |||
3027 | DWARFDIE die = debug_info->GetDIE (die_ref); | |||
3028 | ||||
3029 | if (die) | |||
3030 | { | |||
3031 | if (!DIEInDeclContext (parent_decl_ctx, die)) | |||
3032 | continue; // The containing decl contexts don't match | |||
3033 | ||||
3034 | DWARFASTParser *dwarf_ast = die.GetDWARFParser(); | |||
3035 | if (dwarf_ast) | |||
3036 | { | |||
3037 | namespace_decl_ctx = dwarf_ast->GetDeclContextForUIDFromDWARF (die); | |||
3038 | if (namespace_decl_ctx) | |||
3039 | break; | |||
3040 | } | |||
3041 | } | |||
3042 | else | |||
3043 | { | |||
3044 | if (m_using_apple_tables) | |||
3045 | { | |||
3046 | GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_namespaces accelerator table had bad die 0x%8.8x for '%s')\n", | |||
3047 | die_ref.die_offset, name.GetCString()); | |||
3048 | } | |||
3049 | } | |||
3050 | ||||
3051 | } | |||
3052 | } | |||
3053 | } | |||
3054 | if (log && namespace_decl_ctx) | |||
3055 | { | |||
3056 | GetObjectFile()->GetModule()->LogMessage (log, | |||
3057 | "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => CompilerDeclContext(%p/%p) \"%s\"", | |||
3058 | name.GetCString(), | |||
3059 | static_cast<const void*>(namespace_decl_ctx.GetTypeSystem()), | |||
3060 | static_cast<const void*>(namespace_decl_ctx.GetOpaqueDeclContext()), | |||
3061 | namespace_decl_ctx.GetName().AsCString("<NULL>")); | |||
3062 | } | |||
3063 | ||||
3064 | return namespace_decl_ctx; | |||
3065 | } | |||
3066 | ||||
3067 | TypeSP | |||
3068 | SymbolFileDWARF::GetTypeForDIE (const DWARFDIE &die, bool resolve_function_context) | |||
3069 | { | |||
3070 | TypeSP type_sp; | |||
3071 | if (die) | |||
3072 | { | |||
3073 | Type *type_ptr = GetDIEToType().lookup (die.GetDIE()); | |||
3074 | if (type_ptr == NULL__null) | |||
3075 | { | |||
3076 | CompileUnit* lldb_cu = GetCompUnitForDWARFCompUnit(die.GetCU()); | |||
3077 | assert (lldb_cu)((lldb_cu) ? static_cast<void> (0) : __assert_fail ("lldb_cu" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 3077, __PRETTY_FUNCTION__)); | |||
3078 | SymbolContext sc(lldb_cu); | |||
3079 | const DWARFDebugInfoEntry* parent_die = die.GetParent().GetDIE(); | |||
3080 | while (parent_die != nullptr) | |||
3081 | { | |||
3082 | if (parent_die->Tag() == DW_TAG_subprogram) | |||
3083 | break; | |||
3084 | parent_die = parent_die->GetParent(); | |||
3085 | } | |||
3086 | SymbolContext sc_backup = sc; | |||
3087 | if (resolve_function_context && parent_die != nullptr && !GetFunction(DWARFDIE(die.GetCU(),parent_die), sc)) | |||
3088 | sc = sc_backup; | |||
3089 | ||||
3090 | type_sp = ParseType(sc, die, NULL__null); | |||
3091 | } | |||
3092 | else if (type_ptr != DIE_IS_BEING_PARSED((lldb_private::Type*)1)) | |||
3093 | { | |||
3094 | // Grab the existing type from the master types lists | |||
3095 | type_sp = type_ptr->shared_from_this(); | |||
3096 | } | |||
3097 | ||||
3098 | } | |||
3099 | return type_sp; | |||
3100 | } | |||
3101 | ||||
3102 | ||||
3103 | DWARFDIE | |||
3104 | SymbolFileDWARF::GetDeclContextDIEContainingDIE (const DWARFDIE &orig_die) | |||
3105 | { | |||
3106 | if (orig_die) | |||
3107 | { | |||
3108 | DWARFDIE die = orig_die; | |||
3109 | ||||
3110 | while (die) | |||
3111 | { | |||
3112 | // If this is the original DIE that we are searching for a declaration | |||
3113 | // for, then don't look in the cache as we don't want our own decl | |||
3114 | // context to be our decl context... | |||
3115 | if (orig_die != die) | |||
3116 | { | |||
3117 | switch (die.Tag()) | |||
3118 | { | |||
3119 | case DW_TAG_compile_unit: | |||
3120 | case DW_TAG_namespace: | |||
3121 | case DW_TAG_structure_type: | |||
3122 | case DW_TAG_union_type: | |||
3123 | case DW_TAG_class_type: | |||
3124 | case DW_TAG_lexical_block: | |||
3125 | case DW_TAG_subprogram: | |||
3126 | return die; | |||
3127 | ||||
3128 | default: | |||
3129 | break; | |||
3130 | } | |||
3131 | } | |||
3132 | ||||
3133 | DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification); | |||
3134 | if (spec_die) | |||
3135 | { | |||
3136 | DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(spec_die); | |||
3137 | if (decl_ctx_die) | |||
3138 | return decl_ctx_die; | |||
3139 | } | |||
3140 | ||||
3141 | DWARFDIE abs_die = die.GetReferencedDIE(DW_AT_abstract_origin); | |||
3142 | if (abs_die) | |||
3143 | { | |||
3144 | DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(abs_die); | |||
3145 | if (decl_ctx_die) | |||
3146 | return decl_ctx_die; | |||
3147 | } | |||
3148 | ||||
3149 | die = die.GetParent(); | |||
3150 | } | |||
3151 | } | |||
3152 | return DWARFDIE(); | |||
3153 | } | |||
3154 | ||||
3155 | ||||
3156 | Symbol * | |||
3157 | SymbolFileDWARF::GetObjCClassSymbol (const ConstString &objc_class_name) | |||
3158 | { | |||
3159 | Symbol *objc_class_symbol = NULL__null; | |||
3160 | if (m_obj_file) | |||
3161 | { | |||
3162 | Symtab *symtab = m_obj_file->GetSymtab (); | |||
3163 | if (symtab) | |||
3164 | { | |||
3165 | objc_class_symbol = symtab->FindFirstSymbolWithNameAndType (objc_class_name, | |||
3166 | eSymbolTypeObjCClass, | |||
3167 | Symtab::eDebugNo, | |||
3168 | Symtab::eVisibilityAny); | |||
3169 | } | |||
3170 | } | |||
3171 | return objc_class_symbol; | |||
3172 | } | |||
3173 | ||||
3174 | // Some compilers don't emit the DW_AT_APPLE_objc_complete_type attribute. If they don't | |||
3175 | // then we can end up looking through all class types for a complete type and never find | |||
3176 | // the full definition. We need to know if this attribute is supported, so we determine | |||
3177 | // this here and cache th result. We also need to worry about the debug map DWARF file | |||
3178 | // if we are doing darwin DWARF in .o file debugging. | |||
3179 | bool | |||
3180 | SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu) | |||
3181 | { | |||
3182 | if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) | |||
3183 | { | |||
3184 | m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo; | |||
3185 | if (cu && cu->Supports_DW_AT_APPLE_objc_complete_type()) | |||
3186 | m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes; | |||
3187 | else | |||
3188 | { | |||
3189 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
3190 | const uint32_t num_compile_units = GetNumCompileUnits(); | |||
3191 | for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) | |||
3192 | { | |||
3193 | DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); | |||
3194 | if (dwarf_cu != cu && dwarf_cu->Supports_DW_AT_APPLE_objc_complete_type()) | |||
3195 | { | |||
3196 | m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes; | |||
3197 | break; | |||
3198 | } | |||
3199 | } | |||
3200 | } | |||
3201 | if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolNo && GetDebugMapSymfile ()) | |||
3202 | return m_debug_map_symfile->Supports_DW_AT_APPLE_objc_complete_type (this); | |||
3203 | } | |||
3204 | return m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolYes; | |||
3205 | } | |||
3206 | ||||
3207 | // This function can be used when a DIE is found that is a forward declaration | |||
3208 | // DIE and we want to try and find a type that has the complete definition. | |||
3209 | TypeSP | |||
3210 | SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die, | |||
3211 | const ConstString &type_name, | |||
3212 | bool must_be_implementation) | |||
3213 | { | |||
3214 | ||||
3215 | TypeSP type_sp; | |||
3216 | ||||
3217 | if (!type_name || (must_be_implementation && !GetObjCClassSymbol (type_name))) | |||
3218 | return type_sp; | |||
3219 | ||||
3220 | DIEArray die_offsets; | |||
3221 | ||||
3222 | if (m_using_apple_tables) | |||
3223 | { | |||
3224 | if (m_apple_types_ap.get()) | |||
3225 | { | |||
3226 | const char *name_cstr = type_name.GetCString(); | |||
3227 | m_apple_types_ap->FindCompleteObjCClassByName (name_cstr, die_offsets, must_be_implementation); | |||
3228 | } | |||
3229 | } | |||
3230 | else | |||
3231 | { | |||
3232 | if (!m_indexed) | |||
3233 | Index (); | |||
3234 | ||||
3235 | m_type_index.Find (type_name, die_offsets); | |||
3236 | } | |||
3237 | ||||
3238 | const size_t num_matches = die_offsets.size(); | |||
3239 | ||||
3240 | if (num_matches) | |||
3241 | { | |||
3242 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
3243 | for (size_t i=0; i<num_matches; ++i) | |||
3244 | { | |||
3245 | const DIERef& die_ref = die_offsets[i]; | |||
3246 | DWARFDIE type_die = debug_info->GetDIE (die_ref); | |||
3247 | ||||
3248 | if (type_die) | |||
3249 | { | |||
3250 | bool try_resolving_type = false; | |||
3251 | ||||
3252 | // Don't try and resolve the DIE we are looking for with the DIE itself! | |||
3253 | if (type_die != die) | |||
3254 | { | |||
3255 | switch (type_die.Tag()) | |||
3256 | { | |||
3257 | case DW_TAG_class_type: | |||
3258 | case DW_TAG_structure_type: | |||
3259 | try_resolving_type = true; | |||
3260 | break; | |||
3261 | default: | |||
3262 | break; | |||
3263 | } | |||
3264 | } | |||
3265 | ||||
3266 | if (try_resolving_type) | |||
3267 | { | |||
3268 | if (must_be_implementation && type_die.Supports_DW_AT_APPLE_objc_complete_type()) | |||
3269 | try_resolving_type = type_die.GetAttributeValueAsUnsigned (DW_AT_APPLE_objc_complete_type, 0); | |||
3270 | ||||
3271 | if (try_resolving_type) | |||
3272 | { | |||
3273 | Type *resolved_type = ResolveType (type_die, false, true); | |||
3274 | if (resolved_type && resolved_type != DIE_IS_BEING_PARSED((lldb_private::Type*)1)) | |||
3275 | { | |||
3276 | DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n", | |||
3277 | die.GetID(), | |||
3278 | m_obj_file->GetFileSpec().GetFilename().AsCString("<Unknown>"), | |||
3279 | type_die.GetID(), | |||
3280 | type_cu->GetID()); | |||
3281 | ||||
3282 | if (die) | |||
3283 | GetDIEToType()[die.GetDIE()] = resolved_type; | |||
3284 | type_sp = resolved_type->shared_from_this(); | |||
3285 | break; | |||
3286 | } | |||
3287 | } | |||
3288 | } | |||
3289 | } | |||
3290 | else | |||
3291 | { | |||
3292 | if (m_using_apple_tables) | |||
3293 | { | |||
3294 | GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", | |||
3295 | die_ref.die_offset, type_name.GetCString()); | |||
3296 | } | |||
3297 | } | |||
3298 | ||||
3299 | } | |||
3300 | } | |||
3301 | return type_sp; | |||
3302 | } | |||
3303 | ||||
3304 | ||||
3305 | //---------------------------------------------------------------------- | |||
3306 | // This function helps to ensure that the declaration contexts match for | |||
3307 | // two different DIEs. Often times debug information will refer to a | |||
3308 | // forward declaration of a type (the equivalent of "struct my_struct;". | |||
3309 | // There will often be a declaration of that type elsewhere that has the | |||
3310 | // full definition. When we go looking for the full type "my_struct", we | |||
3311 | // will find one or more matches in the accelerator tables and we will | |||
3312 | // then need to make sure the type was in the same declaration context | |||
3313 | // as the original DIE. This function can efficiently compare two DIEs | |||
3314 | // and will return true when the declaration context matches, and false | |||
3315 | // when they don't. | |||
3316 | //---------------------------------------------------------------------- | |||
3317 | bool | |||
3318 | SymbolFileDWARF::DIEDeclContextsMatch (const DWARFDIE &die1, | |||
3319 | const DWARFDIE &die2) | |||
3320 | { | |||
3321 | if (die1 == die2) | |||
3322 | return true; | |||
3323 | ||||
3324 | DWARFDIECollection decl_ctx_1; | |||
3325 | DWARFDIECollection decl_ctx_2; | |||
3326 | //The declaration DIE stack is a stack of the declaration context | |||
3327 | // DIEs all the way back to the compile unit. If a type "T" is | |||
3328 | // declared inside a class "B", and class "B" is declared inside | |||
3329 | // a class "A" and class "A" is in a namespace "lldb", and the | |||
3330 | // namespace is in a compile unit, there will be a stack of DIEs: | |||
3331 | // | |||
3332 | // [0] DW_TAG_class_type for "B" | |||
3333 | // [1] DW_TAG_class_type for "A" | |||
3334 | // [2] DW_TAG_namespace for "lldb" | |||
3335 | // [3] DW_TAG_compile_unit for the source file. | |||
3336 | // | |||
3337 | // We grab both contexts and make sure that everything matches | |||
3338 | // all the way back to the compiler unit. | |||
3339 | ||||
3340 | // First lets grab the decl contexts for both DIEs | |||
3341 | die1.GetDeclContextDIEs (decl_ctx_1); | |||
3342 | die2.GetDeclContextDIEs (decl_ctx_2); | |||
3343 | // Make sure the context arrays have the same size, otherwise | |||
3344 | // we are done | |||
3345 | const size_t count1 = decl_ctx_1.Size(); | |||
3346 | const size_t count2 = decl_ctx_2.Size(); | |||
3347 | if (count1 != count2) | |||
3348 | return false; | |||
3349 | ||||
3350 | // Make sure the DW_TAG values match all the way back up the | |||
3351 | // compile unit. If they don't, then we are done. | |||
3352 | DWARFDIE decl_ctx_die1; | |||
3353 | DWARFDIE decl_ctx_die2; | |||
3354 | size_t i; | |||
3355 | for (i=0; i<count1; i++) | |||
3356 | { | |||
3357 | decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex (i); | |||
3358 | decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex (i); | |||
3359 | if (decl_ctx_die1.Tag() != decl_ctx_die2.Tag()) | |||
3360 | return false; | |||
3361 | } | |||
3362 | #if defined LLDB_CONFIGURATION_DEBUG | |||
3363 | ||||
3364 | // Make sure the top item in the decl context die array is always | |||
3365 | // DW_TAG_compile_unit. If it isn't then something went wrong in | |||
3366 | // the DWARFDIE::GetDeclContextDIEs() function... | |||
3367 | assert (decl_ctx_1.GetDIEAtIndex (count1 - 1).Tag() == DW_TAG_compile_unit)((decl_ctx_1.GetDIEAtIndex (count1 - 1).Tag() == DW_TAG_compile_unit ) ? static_cast<void> (0) : __assert_fail ("decl_ctx_1.GetDIEAtIndex (count1 - 1).Tag() == DW_TAG_compile_unit" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 3367, __PRETTY_FUNCTION__)); | |||
3368 | ||||
3369 | #endif | |||
3370 | // Always skip the compile unit when comparing by only iterating up to | |||
3371 | // "count - 1". Here we compare the names as we go. | |||
3372 | for (i=0; i<count1 - 1; i++) | |||
3373 | { | |||
3374 | decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex (i); | |||
3375 | decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex (i); | |||
3376 | const char *name1 = decl_ctx_die1.GetName(); | |||
3377 | const char *name2 = decl_ctx_die2.GetName(); | |||
3378 | // If the string was from a DW_FORM_strp, then the pointer will often | |||
3379 | // be the same! | |||
3380 | if (name1 == name2) | |||
3381 | continue; | |||
3382 | ||||
3383 | // Name pointers are not equal, so only compare the strings | |||
3384 | // if both are not NULL. | |||
3385 | if (name1 && name2) | |||
3386 | { | |||
3387 | // If the strings don't compare, we are done... | |||
3388 | if (strcmp(name1, name2) != 0) | |||
3389 | return false; | |||
3390 | } | |||
3391 | else | |||
3392 | { | |||
3393 | // One name was NULL while the other wasn't | |||
3394 | return false; | |||
3395 | } | |||
3396 | } | |||
3397 | // We made it through all of the checks and the declaration contexts | |||
3398 | // are equal. | |||
3399 | return true; | |||
3400 | } | |||
3401 | ||||
3402 | ||||
3403 | TypeSP | |||
3404 | SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &dwarf_decl_ctx) | |||
3405 | { | |||
3406 | TypeSP type_sp; | |||
3407 | ||||
3408 | const uint32_t dwarf_decl_ctx_count = dwarf_decl_ctx.GetSize(); | |||
3409 | if (dwarf_decl_ctx_count > 0) | |||
3410 | { | |||
3411 | const ConstString type_name(dwarf_decl_ctx[0].name); | |||
3412 | const dw_tag_t tag = dwarf_decl_ctx[0].tag; | |||
3413 | ||||
3414 | if (type_name) | |||
3415 | { | |||
3416 | Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION(1u << 7)|DWARF_LOG_LOOKUPS(1u << 6))); | |||
3417 | if (log) | |||
3418 | { | |||
3419 | GetObjectFile()->GetModule()->LogMessage (log, | |||
3420 | "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s')", | |||
3421 | DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), | |||
3422 | dwarf_decl_ctx.GetQualifiedName()); | |||
3423 | } | |||
3424 | ||||
3425 | DIEArray die_offsets; | |||
3426 | ||||
3427 | if (m_using_apple_tables) | |||
3428 | { | |||
3429 | if (m_apple_types_ap.get()) | |||
3430 | { | |||
3431 | const bool has_tag = m_apple_types_ap->GetHeader().header_data.ContainsAtom (DWARFMappedHash::eAtomTypeTag); | |||
3432 | const bool has_qualified_name_hash = m_apple_types_ap->GetHeader().header_data.ContainsAtom (DWARFMappedHash::eAtomTypeQualNameHash); | |||
3433 | if (has_tag && has_qualified_name_hash) | |||
3434 | { | |||
3435 | const char *qualified_name = dwarf_decl_ctx.GetQualifiedName(); | |||
3436 | const uint32_t qualified_name_hash = MappedHash::HashStringUsingDJB (qualified_name); | |||
3437 | if (log) | |||
3438 | GetObjectFile()->GetModule()->LogMessage (log,"FindByNameAndTagAndQualifiedNameHash()"); | |||
3439 | m_apple_types_ap->FindByNameAndTagAndQualifiedNameHash (type_name.GetCString(), tag, qualified_name_hash, die_offsets); | |||
3440 | } | |||
3441 | else if (has_tag) | |||
3442 | { | |||
3443 | if (log) | |||
3444 | GetObjectFile()->GetModule()->LogMessage (log,"FindByNameAndTag()"); | |||
3445 | m_apple_types_ap->FindByNameAndTag (type_name.GetCString(), tag, die_offsets); | |||
3446 | } | |||
3447 | else | |||
3448 | { | |||
3449 | m_apple_types_ap->FindByName (type_name.GetCString(), die_offsets); | |||
3450 | } | |||
3451 | } | |||
3452 | } | |||
3453 | else | |||
3454 | { | |||
3455 | if (!m_indexed) | |||
3456 | Index (); | |||
3457 | ||||
3458 | m_type_index.Find (type_name, die_offsets); | |||
3459 | } | |||
3460 | ||||
3461 | const size_t num_matches = die_offsets.size(); | |||
3462 | ||||
3463 | ||||
3464 | if (num_matches) | |||
3465 | { | |||
3466 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
3467 | for (size_t i=0; i<num_matches; ++i) | |||
3468 | { | |||
3469 | const DIERef& die_ref = die_offsets[i]; | |||
3470 | DWARFDIE type_die = debug_info->GetDIE (die_ref); | |||
3471 | ||||
3472 | if (type_die) | |||
3473 | { | |||
3474 | bool try_resolving_type = false; | |||
3475 | ||||
3476 | // Don't try and resolve the DIE we are looking for with the DIE itself! | |||
3477 | const dw_tag_t type_tag = type_die.Tag(); | |||
3478 | // Make sure the tags match | |||
3479 | if (type_tag == tag) | |||
3480 | { | |||
3481 | // The tags match, lets try resolving this type | |||
3482 | try_resolving_type = true; | |||
3483 | } | |||
3484 | else | |||
3485 | { | |||
3486 | // The tags don't match, but we need to watch our for a | |||
3487 | // forward declaration for a struct and ("struct foo") | |||
3488 | // ends up being a class ("class foo { ... };") or | |||
3489 | // vice versa. | |||
3490 | switch (type_tag) | |||
3491 | { | |||
3492 | case DW_TAG_class_type: | |||
3493 | // We had a "class foo", see if we ended up with a "struct foo { ... };" | |||
3494 | try_resolving_type = (tag == DW_TAG_structure_type); | |||
3495 | break; | |||
3496 | case DW_TAG_structure_type: | |||
3497 | // We had a "struct foo", see if we ended up with a "class foo { ... };" | |||
3498 | try_resolving_type = (tag == DW_TAG_class_type); | |||
3499 | break; | |||
3500 | default: | |||
3501 | // Tags don't match, don't event try to resolve | |||
3502 | // using this type whose name matches.... | |||
3503 | break; | |||
3504 | } | |||
3505 | } | |||
3506 | ||||
3507 | if (try_resolving_type) | |||
3508 | { | |||
3509 | DWARFDeclContext type_dwarf_decl_ctx; | |||
3510 | type_die.GetDWARFDeclContext (type_dwarf_decl_ctx); | |||
3511 | ||||
3512 | if (log) | |||
3513 | { | |||
3514 | GetObjectFile()->GetModule()->LogMessage (log, | |||
3515 | "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') trying die=0x%8.8x (%s)", | |||
3516 | DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), | |||
3517 | dwarf_decl_ctx.GetQualifiedName(), | |||
3518 | type_die.GetOffset(), | |||
3519 | type_dwarf_decl_ctx.GetQualifiedName()); | |||
3520 | } | |||
3521 | ||||
3522 | // Make sure the decl contexts match all the way up | |||
3523 | if (dwarf_decl_ctx == type_dwarf_decl_ctx) | |||
3524 | { | |||
3525 | Type *resolved_type = ResolveType (type_die, false); | |||
3526 | if (resolved_type && resolved_type != DIE_IS_BEING_PARSED((lldb_private::Type*)1)) | |||
3527 | { | |||
3528 | type_sp = resolved_type->shared_from_this(); | |||
3529 | break; | |||
3530 | } | |||
3531 | } | |||
3532 | } | |||
3533 | else | |||
3534 | { | |||
3535 | if (log) | |||
3536 | { | |||
3537 | std::string qualified_name; | |||
3538 | type_die.GetQualifiedName(qualified_name); | |||
3539 | GetObjectFile()->GetModule()->LogMessage (log, | |||
3540 | "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') ignoring die=0x%8.8x (%s)", | |||
3541 | DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), | |||
3542 | dwarf_decl_ctx.GetQualifiedName(), | |||
3543 | type_die.GetOffset(), | |||
3544 | qualified_name.c_str()); | |||
3545 | } | |||
3546 | } | |||
3547 | } | |||
3548 | else | |||
3549 | { | |||
3550 | if (m_using_apple_tables) | |||
3551 | { | |||
3552 | GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", | |||
3553 | die_ref.die_offset, type_name.GetCString()); | |||
3554 | } | |||
3555 | } | |||
3556 | ||||
3557 | } | |||
3558 | } | |||
3559 | } | |||
3560 | } | |||
3561 | return type_sp; | |||
3562 | } | |||
3563 | ||||
3564 | TypeSP | |||
3565 | SymbolFileDWARF::ParseType (const SymbolContext& sc, const DWARFDIE &die, bool *type_is_new_ptr) | |||
3566 | { | |||
3567 | TypeSP type_sp; | |||
3568 | ||||
3569 | if (die) | |||
3570 | { | |||
3571 | TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); | |||
3572 | ||||
3573 | if (type_system) | |||
3574 | { | |||
3575 | DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); | |||
3576 | if (dwarf_ast) | |||
3577 | { | |||
3578 | Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO(1u << 1)); | |||
3579 | type_sp = dwarf_ast->ParseTypeFromDWARF (sc, die, log, type_is_new_ptr); | |||
3580 | if (type_sp) | |||
3581 | { | |||
3582 | TypeList* type_list = GetTypeList(); | |||
3583 | if (type_list) | |||
3584 | type_list->Insert(type_sp); | |||
3585 | } | |||
3586 | } | |||
3587 | } | |||
3588 | } | |||
3589 | ||||
3590 | return type_sp; | |||
3591 | } | |||
3592 | ||||
3593 | size_t | |||
3594 | SymbolFileDWARF::ParseTypes | |||
3595 | ( | |||
3596 | const SymbolContext& sc, | |||
3597 | const DWARFDIE &orig_die, | |||
3598 | bool parse_siblings, | |||
3599 | bool parse_children | |||
3600 | ) | |||
3601 | { | |||
3602 | size_t types_added = 0; | |||
3603 | DWARFDIE die = orig_die; | |||
3604 | while (die) | |||
3605 | { | |||
3606 | bool type_is_new = false; | |||
3607 | if (ParseType(sc, die, &type_is_new).get()) | |||
3608 | { | |||
3609 | if (type_is_new) | |||
3610 | ++types_added; | |||
3611 | } | |||
3612 | ||||
3613 | if (parse_children && die.HasChildren()) | |||
3614 | { | |||
3615 | if (die.Tag() == DW_TAG_subprogram) | |||
3616 | { | |||
3617 | SymbolContext child_sc(sc); | |||
3618 | child_sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get(); | |||
3619 | types_added += ParseTypes(child_sc, die.GetFirstChild(), true, true); | |||
3620 | } | |||
3621 | else | |||
3622 | types_added += ParseTypes(sc, die.GetFirstChild(), true, true); | |||
3623 | } | |||
3624 | ||||
3625 | if (parse_siblings) | |||
3626 | die = die.GetSibling(); | |||
3627 | else | |||
3628 | die.Clear(); | |||
3629 | } | |||
3630 | return types_added; | |||
3631 | } | |||
3632 | ||||
3633 | ||||
3634 | size_t | |||
3635 | SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext &sc) | |||
3636 | { | |||
3637 | assert(sc.comp_unit && sc.function)((sc.comp_unit && sc.function) ? static_cast<void> (0) : __assert_fail ("sc.comp_unit && sc.function", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 3637, __PRETTY_FUNCTION__)); | |||
3638 | size_t functions_added = 0; | |||
3639 | DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); | |||
3640 | if (dwarf_cu) | |||
3641 | { | |||
3642 | const dw_offset_t function_die_offset = sc.function->GetID(); | |||
3643 | DWARFDIE function_die = dwarf_cu->GetDIE (function_die_offset); | |||
3644 | if (function_die) | |||
3645 | { | |||
3646 | ParseFunctionBlocks(sc, &sc.function->GetBlock (false), function_die, LLDB_INVALID_ADDRESS(18446744073709551615UL), 0); | |||
3647 | } | |||
3648 | } | |||
3649 | ||||
3650 | return functions_added; | |||
3651 | } | |||
3652 | ||||
3653 | ||||
3654 | size_t | |||
3655 | SymbolFileDWARF::ParseTypes (const SymbolContext &sc) | |||
3656 | { | |||
3657 | // At least a compile unit must be valid | |||
3658 | assert(sc.comp_unit)((sc.comp_unit) ? static_cast<void> (0) : __assert_fail ("sc.comp_unit", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 3658, __PRETTY_FUNCTION__)); | |||
3659 | size_t types_added = 0; | |||
3660 | DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); | |||
3661 | if (dwarf_cu) | |||
3662 | { | |||
3663 | if (sc.function) | |||
3664 | { | |||
3665 | dw_offset_t function_die_offset = sc.function->GetID(); | |||
3666 | DWARFDIE func_die = dwarf_cu->GetDIE(function_die_offset); | |||
3667 | if (func_die && func_die.HasChildren()) | |||
3668 | { | |||
3669 | types_added = ParseTypes(sc, func_die.GetFirstChild(), true, true); | |||
3670 | } | |||
3671 | } | |||
3672 | else | |||
3673 | { | |||
3674 | DWARFDIE dwarf_cu_die = dwarf_cu->DIE(); | |||
3675 | if (dwarf_cu_die && dwarf_cu_die.HasChildren()) | |||
3676 | { | |||
3677 | types_added = ParseTypes(sc, dwarf_cu_die.GetFirstChild(), true, true); | |||
3678 | } | |||
3679 | } | |||
3680 | } | |||
3681 | ||||
3682 | return types_added; | |||
3683 | } | |||
3684 | ||||
3685 | size_t | |||
3686 | SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc) | |||
3687 | { | |||
3688 | if (sc.comp_unit != NULL__null) | |||
3689 | { | |||
3690 | DWARFDebugInfo* info = DebugInfo(); | |||
3691 | if (info == NULL__null) | |||
3692 | return 0; | |||
3693 | ||||
3694 | if (sc.function) | |||
3695 | { | |||
3696 | DWARFDIE function_die = info->GetDIE(DIERef(sc.function->GetID())); | |||
3697 | ||||
3698 | const dw_addr_t func_lo_pc = function_die.GetAttributeValueAsAddress (DW_AT_low_pc, LLDB_INVALID_ADDRESS(18446744073709551615UL)); | |||
3699 | if (func_lo_pc != LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
3700 | { | |||
3701 | const size_t num_variables = ParseVariables(sc, function_die.GetFirstChild(), func_lo_pc, true, true); | |||
3702 | ||||
3703 | // Let all blocks know they have parse all their variables | |||
3704 | sc.function->GetBlock (false).SetDidParseVariables (true, true); | |||
3705 | return num_variables; | |||
3706 | } | |||
3707 | } | |||
3708 | else if (sc.comp_unit) | |||
3709 | { | |||
3710 | DWARFCompileUnit* dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID()); | |||
3711 | ||||
3712 | if (dwarf_cu == NULL__null) | |||
3713 | return 0; | |||
3714 | ||||
3715 | uint32_t vars_added = 0; | |||
3716 | VariableListSP variables (sc.comp_unit->GetVariableList(false)); | |||
3717 | ||||
3718 | if (variables.get() == NULL__null) | |||
3719 | { | |||
3720 | variables.reset(new VariableList()); | |||
3721 | sc.comp_unit->SetVariableList(variables); | |||
3722 | ||||
3723 | DIEArray die_offsets; | |||
3724 | if (m_using_apple_tables) | |||
3725 | { | |||
3726 | if (m_apple_names_ap.get()) | |||
3727 | { | |||
3728 | DWARFMappedHash::DIEInfoArray hash_data_array; | |||
3729 | if (m_apple_names_ap->AppendAllDIEsInRange (dwarf_cu->GetOffset(), | |||
3730 | dwarf_cu->GetNextCompileUnitOffset(), | |||
3731 | hash_data_array)) | |||
3732 | { | |||
3733 | DWARFMappedHash::ExtractDIEArray (hash_data_array, die_offsets); | |||
3734 | } | |||
3735 | } | |||
3736 | } | |||
3737 | else | |||
3738 | { | |||
3739 | // Index if we already haven't to make sure the compile units | |||
3740 | // get indexed and make their global DIE index list | |||
3741 | if (!m_indexed) | |||
3742 | Index (); | |||
3743 | ||||
3744 | m_global_index.FindAllEntriesForCompileUnit (dwarf_cu->GetOffset(), | |||
3745 | die_offsets); | |||
3746 | } | |||
3747 | ||||
3748 | const size_t num_matches = die_offsets.size(); | |||
3749 | if (num_matches) | |||
3750 | { | |||
3751 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
3752 | for (size_t i=0; i<num_matches; ++i) | |||
3753 | { | |||
3754 | const DIERef& die_ref = die_offsets[i]; | |||
3755 | DWARFDIE die = debug_info->GetDIE (die_ref); | |||
3756 | if (die) | |||
3757 | { | |||
3758 | VariableSP var_sp (ParseVariableDIE(sc, die, LLDB_INVALID_ADDRESS(18446744073709551615UL))); | |||
3759 | if (var_sp) | |||
3760 | { | |||
3761 | variables->AddVariableIfUnique (var_sp); | |||
3762 | ++vars_added; | |||
3763 | } | |||
3764 | } | |||
3765 | else | |||
3766 | { | |||
3767 | if (m_using_apple_tables) | |||
3768 | { | |||
3769 | GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x)\n", die_ref.die_offset); | |||
3770 | } | |||
3771 | } | |||
3772 | ||||
3773 | } | |||
3774 | } | |||
3775 | } | |||
3776 | return vars_added; | |||
3777 | } | |||
3778 | } | |||
3779 | return 0; | |||
3780 | } | |||
3781 | ||||
3782 | VariableSP | |||
3783 | SymbolFileDWARF::ParseVariableDIE | |||
3784 | ( | |||
3785 | const SymbolContext& sc, | |||
3786 | const DWARFDIE &die, | |||
3787 | const lldb::addr_t func_low_pc | |||
3788 | ) | |||
3789 | { | |||
3790 | if (die.GetDWARF() != this) | |||
3791 | return die.GetDWARF()->ParseVariableDIE(sc, die, func_low_pc); | |||
3792 | ||||
3793 | VariableSP var_sp; | |||
3794 | if (!die) | |||
3795 | return var_sp; | |||
3796 | ||||
3797 | var_sp = GetDIEToVariable()[die.GetDIE()]; | |||
3798 | if (var_sp) | |||
3799 | return var_sp; // Already been parsed! | |||
3800 | ||||
3801 | const dw_tag_t tag = die.Tag(); | |||
3802 | ModuleSP module = GetObjectFile()->GetModule(); | |||
3803 | ||||
3804 | if ((tag == DW_TAG_variable) || | |||
3805 | (tag == DW_TAG_constant) || | |||
3806 | (tag == DW_TAG_formal_parameter && sc.function)) | |||
3807 | { | |||
3808 | DWARFAttributes attributes; | |||
3809 | const size_t num_attributes = die.GetAttributes(attributes); | |||
3810 | DWARFDIE spec_die; | |||
3811 | if (num_attributes > 0) | |||
3812 | { | |||
3813 | const char *name = NULL__null; | |||
3814 | const char *mangled = NULL__null; | |||
3815 | Declaration decl; | |||
3816 | uint32_t i; | |||
3817 | DWARFFormValue type_die_form; | |||
3818 | DWARFExpression location(die.GetCU()); | |||
3819 | bool is_external = false; | |||
3820 | bool is_artificial = false; | |||
3821 | bool location_is_const_value_data = false; | |||
3822 | bool has_explicit_location = false; | |||
3823 | DWARFFormValue const_value; | |||
3824 | //AccessType accessibility = eAccessNone; | |||
3825 | ||||
3826 | for (i=0; i<num_attributes; ++i) | |||
3827 | { | |||
3828 | dw_attr_t attr = attributes.AttributeAtIndex(i); | |||
3829 | DWARFFormValue form_value; | |||
3830 | ||||
3831 | if (attributes.ExtractFormValueAtIndex(i, form_value)) | |||
3832 | { | |||
3833 | switch (attr) | |||
3834 | { | |||
3835 | case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; | |||
3836 | case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; | |||
3837 | case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; | |||
3838 | case DW_AT_name: name = form_value.AsCString(); break; | |||
3839 | case DW_AT_linkage_name: | |||
3840 | case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(); break; | |||
3841 | case DW_AT_type: type_die_form = form_value; break; | |||
3842 | case DW_AT_external: is_external = form_value.Boolean(); break; | |||
3843 | case DW_AT_const_value: | |||
3844 | // If we have already found a DW_AT_location attribute, ignore this attribute. | |||
3845 | if (!has_explicit_location) | |||
3846 | { | |||
3847 | location_is_const_value_data = true; | |||
3848 | // The constant value will be either a block, a data value or a string. | |||
3849 | const DWARFDataExtractor& debug_info_data = get_debug_info_data(); | |||
3850 | if (DWARFFormValue::IsBlockForm(form_value.Form())) | |||
3851 | { | |||
3852 | // Retrieve the value as a block expression. | |||
3853 | uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); | |||
3854 | uint32_t block_length = form_value.Unsigned(); | |||
3855 | location.CopyOpcodeData(module, debug_info_data, block_offset, block_length); | |||
3856 | } | |||
3857 | else if (DWARFFormValue::IsDataForm(form_value.Form())) | |||
3858 | { | |||
3859 | // Retrieve the value as a data expression. | |||
3860 | DWARFFormValue::FixedFormSizes fixed_form_sizes = | |||
3861 | DWARFFormValue::GetFixedFormSizesForAddressSize ( | |||
3862 | attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), | |||
3863 | attributes.CompileUnitAtIndex(i)->IsDWARF64()); | |||
3864 | uint32_t data_offset = attributes.DIEOffsetAtIndex(i); | |||
3865 | uint32_t data_length = fixed_form_sizes.GetSize(form_value.Form()); | |||
3866 | if (data_length == 0) | |||
3867 | { | |||
3868 | const uint8_t *data_pointer = form_value.BlockData(); | |||
3869 | if (data_pointer) | |||
3870 | { | |||
3871 | form_value.Unsigned(); | |||
3872 | } | |||
3873 | else if (DWARFFormValue::IsDataForm(form_value.Form())) | |||
3874 | { | |||
3875 | // we need to get the byte size of the type later after we create the variable | |||
3876 | const_value = form_value; | |||
3877 | } | |||
3878 | } | |||
3879 | else | |||
3880 | location.CopyOpcodeData(module, debug_info_data, data_offset, data_length); | |||
3881 | } | |||
3882 | else | |||
3883 | { | |||
3884 | // Retrieve the value as a string expression. | |||
3885 | if (form_value.Form() == DW_FORM_strp) | |||
3886 | { | |||
3887 | DWARFFormValue::FixedFormSizes fixed_form_sizes = | |||
3888 | DWARFFormValue::GetFixedFormSizesForAddressSize ( | |||
3889 | attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), | |||
3890 | attributes.CompileUnitAtIndex(i)->IsDWARF64()); | |||
3891 | uint32_t data_offset = attributes.DIEOffsetAtIndex(i); | |||
3892 | uint32_t data_length = fixed_form_sizes.GetSize(form_value.Form()); | |||
3893 | location.CopyOpcodeData(module, debug_info_data, data_offset, data_length); | |||
3894 | } | |||
3895 | else | |||
3896 | { | |||
3897 | const char *str = form_value.AsCString(); | |||
3898 | uint32_t string_offset = str - (const char *)debug_info_data.GetDataStart(); | |||
3899 | uint32_t string_length = strlen(str) + 1; | |||
3900 | location.CopyOpcodeData(module, debug_info_data, string_offset, string_length); | |||
3901 | } | |||
3902 | } | |||
3903 | } | |||
3904 | break; | |||
3905 | case DW_AT_location: | |||
3906 | { | |||
3907 | location_is_const_value_data = false; | |||
3908 | has_explicit_location = true; | |||
3909 | if (form_value.BlockData()) | |||
3910 | { | |||
3911 | const DWARFDataExtractor& debug_info_data = get_debug_info_data(); | |||
3912 | ||||
3913 | uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); | |||
3914 | uint32_t block_length = form_value.Unsigned(); | |||
3915 | location.CopyOpcodeData(module, get_debug_info_data(), block_offset, block_length); | |||
3916 | } | |||
3917 | else | |||
3918 | { | |||
3919 | const DWARFDataExtractor& debug_loc_data = get_debug_loc_data(); | |||
3920 | const dw_offset_t debug_loc_offset = form_value.Unsigned(); | |||
3921 | ||||
3922 | size_t loc_list_length = DWARFExpression::LocationListSize(die.GetCU(), debug_loc_data, debug_loc_offset); | |||
3923 | if (loc_list_length > 0) | |||
3924 | { | |||
3925 | location.CopyOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length); | |||
3926 | assert (func_low_pc != LLDB_INVALID_ADDRESS)((func_low_pc != (18446744073709551615UL)) ? static_cast<void > (0) : __assert_fail ("func_low_pc != (18446744073709551615UL)" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn254942/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp" , 3926, __PRETTY_FUNCTION__)); | |||
3927 | location.SetLocationListSlide (func_low_pc - attributes.CompileUnitAtIndex(i)->GetBaseAddress()); | |||
3928 | } | |||
3929 | } | |||
3930 | } | |||
3931 | break; | |||
3932 | case DW_AT_specification: | |||
3933 | { | |||
3934 | DWARFDebugInfo* debug_info = DebugInfo(); | |||
3935 | if (debug_info) | |||
3936 | spec_die = debug_info->GetDIE(DIERef(form_value)); | |||
3937 | break; | |||
3938 | } | |||
3939 | case DW_AT_artificial: is_artificial = form_value.Boolean(); break; | |||
3940 | case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; | |||
3941 | case DW_AT_declaration: | |||
3942 | case DW_AT_description: | |||
3943 | case DW_AT_endianity: | |||
3944 | case DW_AT_segment: | |||
3945 | case DW_AT_start_scope: | |||
3946 | case DW_AT_visibility: | |||
3947 | default: | |||
3948 | case DW_AT_abstract_origin: | |||
3949 | case DW_AT_sibling: | |||
3950 | break; | |||
3951 | } | |||
3952 | } | |||
3953 | } | |||
3954 | ||||
3955 | const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die); | |||
3956 | const dw_tag_t parent_tag = die.GetParent().Tag(); | |||
3957 | bool is_static_member = parent_tag == DW_TAG_compile_unit && (parent_context_die.Tag() == DW_TAG_class_type || parent_context_die.Tag() == DW_TAG_structure_type); | |||
3958 | ||||
3959 | ValueType scope = eValueTypeInvalid; | |||
3960 | ||||
3961 | const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die); | |||
3962 | SymbolContextScope * symbol_context_scope = NULL__null; | |||
3963 | ||||
3964 | if (!mangled) | |||
3965 | { | |||
3966 | // LLDB relies on the mangled name (DW_TAG_linkage_name or DW_AT_MIPS_linkage_name) to | |||
3967 | // generate fully qualified names of global variables with commands like "frame var j". | |||
3968 | // For example, if j were an int variable holding a value 4 and declared in a namespace | |||
3969 | // B which in turn is contained in a namespace A, the command "frame var j" returns | |||
3970 | // "(int) A::B::j = 4". If the compiler does not emit a linkage name, we should be able | |||
3971 | // to generate a fully qualified name from the declaration context. | |||
3972 | if (parent_tag == DW_TAG_compile_unit && | |||
3973 | Language::LanguageIsCPlusPlus(die.GetLanguage())) | |||
3974 | { | |||
3975 | DWARFDeclContext decl_ctx; | |||
3976 | ||||
3977 | die.GetDWARFDeclContext(decl_ctx); | |||
3978 | mangled = decl_ctx.GetQualifiedNameAsConstString().GetCString(); | |||
3979 | } | |||
3980 | } | |||
3981 | ||||
3982 | // DWARF doesn't specify if a DW_TAG_variable is a local, global | |||
3983 | // or static variable, so we have to do a little digging by | |||
3984 | // looking at the location of a variable to see if it contains | |||
3985 | // a DW_OP_addr opcode _somewhere_ in the definition. I say | |||
3986 | // somewhere because clang likes to combine small global variables | |||
3987 | // into the same symbol and have locations like: | |||
3988 | // DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus | |||
3989 | // So if we don't have a DW_TAG_formal_parameter, we can look at | |||
3990 | // the location to see if it contains a DW_OP_addr opcode, and | |||
3991 | // then we can correctly classify our variables. | |||
3992 | if (tag == DW_TAG_formal_parameter) | |||
3993 | scope = eValueTypeVariableArgument; | |||
3994 | else | |||
3995 | { | |||
3996 | bool op_error = false; | |||
3997 | // Check if the location has a DW_OP_addr with any address value... | |||
3998 | lldb::addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
3999 | if (!location_is_const_value_data) | |||
4000 | { | |||
4001 | location_DW_OP_addr = location.GetLocation_DW_OP_addr (0, op_error); | |||
4002 | if (op_error) | |||
4003 | { | |||
4004 | StreamString strm; | |||
4005 | location.DumpLocationForAddress (&strm, eDescriptionLevelFull, 0, 0, NULL__null); | |||
4006 | GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die.GetOffset(), die.GetTagAsCString(), strm.GetString().c_str()); | |||
4007 | } | |||
4008 | } | |||
4009 | ||||
4010 | if (location_DW_OP_addr != LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
4011 | { | |||
4012 | if (is_external) | |||
4013 | scope = eValueTypeVariableGlobal; | |||
4014 | else | |||
4015 | scope = eValueTypeVariableStatic; | |||
4016 | ||||
4017 | ||||
4018 | SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile (); | |||
4019 | ||||
4020 | if (debug_map_symfile) | |||
4021 | { | |||
4022 | // When leaving the DWARF in the .o files on darwin, | |||
4023 | // when we have a global variable that wasn't initialized, | |||
4024 | // the .o file might not have allocated a virtual | |||
4025 | // address for the global variable. In this case it will | |||
4026 | // have created a symbol for the global variable | |||
4027 | // that is undefined/data and external and the value will | |||
4028 | // be the byte size of the variable. When we do the | |||
4029 | // address map in SymbolFileDWARFDebugMap we rely on | |||
4030 | // having an address, we need to do some magic here | |||
4031 | // so we can get the correct address for our global | |||
4032 | // variable. The address for all of these entries | |||
4033 | // will be zero, and there will be an undefined symbol | |||
4034 | // in this object file, and the executable will have | |||
4035 | // a matching symbol with a good address. So here we | |||
4036 | // dig up the correct address and replace it in the | |||
4037 | // location for the variable, and set the variable's | |||
4038 | // symbol context scope to be that of the main executable | |||
4039 | // so the file address will resolve correctly. | |||
4040 | bool linked_oso_file_addr = false; | |||
4041 | if (is_external && location_DW_OP_addr == 0) | |||
4042 | { | |||
4043 | // we have a possible uninitialized extern global | |||
4044 | ConstString const_name(mangled ? mangled : name); | |||
4045 | ObjectFile *debug_map_objfile = debug_map_symfile->GetObjectFile(); | |||
4046 | if (debug_map_objfile) | |||
4047 | { | |||
4048 | Symtab *debug_map_symtab = debug_map_objfile->GetSymtab(); | |||
4049 | if (debug_map_symtab) | |||
4050 | { | |||
4051 | Symbol *exe_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name, | |||
4052 | eSymbolTypeData, | |||
4053 | Symtab::eDebugYes, | |||
4054 | Symtab::eVisibilityExtern); | |||
4055 | if (exe_symbol) | |||
4056 | { | |||
4057 | if (exe_symbol->ValueIsAddress()) | |||
4058 | { | |||
4059 | const addr_t exe_file_addr = exe_symbol->GetAddressRef().GetFileAddress(); | |||
4060 | if (exe_file_addr != LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
4061 | { | |||
4062 | if (location.Update_DW_OP_addr (exe_file_addr)) | |||
4063 | { | |||
4064 | linked_oso_file_addr = true; | |||
4065 | symbol_context_scope = exe_symbol; | |||
4066 | } | |||
4067 | } | |||
4068 | } | |||
4069 | } | |||
4070 | } | |||
4071 | } | |||
4072 | } | |||
4073 | ||||
4074 | if (!linked_oso_file_addr) | |||
4075 | { | |||
4076 | // The DW_OP_addr is not zero, but it contains a .o file address which | |||
4077 | // needs to be linked up correctly. | |||
4078 | const lldb::addr_t exe_file_addr = debug_map_symfile->LinkOSOFileAddress(this, location_DW_OP_addr); | |||
4079 | if (exe_file_addr != LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
4080 | { | |||
4081 | // Update the file address for this variable | |||
4082 | location.Update_DW_OP_addr (exe_file_addr); | |||
4083 | } | |||
4084 | else | |||
4085 | { | |||
4086 | // Variable didn't make it into the final executable | |||
4087 | return var_sp; | |||
4088 | } | |||
4089 | } | |||
4090 | } | |||
4091 | } | |||
4092 | else | |||
4093 | { | |||
4094 | scope = eValueTypeVariableLocal; | |||
4095 | } | |||
4096 | } | |||
4097 | ||||
4098 | if (symbol_context_scope == NULL__null) | |||
4099 | { | |||
4100 | switch (parent_tag) | |||
4101 | { | |||
4102 | case DW_TAG_subprogram: | |||
4103 | case DW_TAG_inlined_subroutine: | |||
4104 | case DW_TAG_lexical_block: | |||
4105 | if (sc.function) | |||
4106 | { | |||
4107 | symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); | |||
4108 | if (symbol_context_scope == NULL__null) | |||
4109 | symbol_context_scope = sc.function; | |||
4110 | } | |||
4111 | break; | |||
4112 | ||||
4113 | default: | |||
4114 | symbol_context_scope = sc.comp_unit; | |||
4115 | break; | |||
4116 | } | |||
4117 | } | |||
4118 | ||||
4119 | if (symbol_context_scope) | |||
4120 | { | |||
4121 | SymbolFileTypeSP type_sp(new SymbolFileType(*this, DIERef(type_die_form).GetUID())); | |||
4122 | ||||
4123 | if (const_value.Form() && type_sp && type_sp->GetType()) | |||
4124 | location.CopyOpcodeData(const_value.Unsigned(), type_sp->GetType()->GetByteSize(), die.GetCU()->GetAddressByteSize()); | |||
4125 | ||||
4126 | var_sp.reset (new Variable (die.GetID(), | |||
4127 | name, | |||
4128 | mangled, | |||
4129 | type_sp, | |||
4130 | scope, | |||
4131 | symbol_context_scope, | |||
4132 | &decl, | |||
4133 | location, | |||
4134 | is_external, | |||
4135 | is_artificial, | |||
4136 | is_static_member)); | |||
4137 | ||||
4138 | var_sp->SetLocationIsConstantValueData (location_is_const_value_data); | |||
4139 | } | |||
4140 | else | |||
4141 | { | |||
4142 | // Not ready to parse this variable yet. It might be a global | |||
4143 | // or static variable that is in a function scope and the function | |||
4144 | // in the symbol context wasn't filled in yet | |||
4145 | return var_sp; | |||
4146 | } | |||
4147 | } | |||
4148 | // Cache var_sp even if NULL (the variable was just a specification or | |||
4149 | // was missing vital information to be able to be displayed in the debugger | |||
4150 | // (missing location due to optimization, etc)) so we don't re-parse | |||
4151 | // this DIE over and over later... | |||
4152 | GetDIEToVariable()[die.GetDIE()] = var_sp; | |||
4153 | if (spec_die) | |||
4154 | GetDIEToVariable()[spec_die.GetDIE()] = var_sp; | |||
4155 | } | |||
4156 | return var_sp; | |||
4157 | } | |||
4158 | ||||
4159 | ||||
4160 | DWARFDIE | |||
4161 | SymbolFileDWARF::FindBlockContainingSpecification (const DIERef& func_die_ref, | |||
4162 | dw_offset_t spec_block_die_offset) | |||
4163 | { | |||
4164 | // Give the concrete function die specified by "func_die_offset", find the | |||
4165 | // concrete block whose DW_AT_specification or DW_AT_abstract_origin points | |||
4166 | // to "spec_block_die_offset" | |||
4167 | return FindBlockContainingSpecification (DebugInfo()->GetDIE (func_die_ref), spec_block_die_offset); | |||
4168 | } | |||
4169 | ||||
4170 | ||||
4171 | DWARFDIE | |||
4172 | SymbolFileDWARF::FindBlockContainingSpecification(const DWARFDIE &die, | |||
4173 | dw_offset_t spec_block_die_offset) | |||
4174 | { | |||
4175 | if (die) | |||
4176 | { | |||
4177 | switch (die.Tag()) | |||
4178 | { | |||
4179 | case DW_TAG_subprogram: | |||
4180 | case DW_TAG_inlined_subroutine: | |||
4181 | case DW_TAG_lexical_block: | |||
4182 | { | |||
4183 | if (die.GetAttributeValueAsReference (DW_AT_specification, DW_INVALID_OFFSET(~(dw_offset_t)0)) == spec_block_die_offset) | |||
4184 | return die; | |||
4185 | ||||
4186 | if (die.GetAttributeValueAsReference (DW_AT_abstract_origin, DW_INVALID_OFFSET(~(dw_offset_t)0)) == spec_block_die_offset) | |||
4187 | return die; | |||
4188 | } | |||
4189 | break; | |||
4190 | } | |||
4191 | ||||
4192 | // Give the concrete function die specified by "func_die_offset", find the | |||
4193 | // concrete block whose DW_AT_specification or DW_AT_abstract_origin points | |||
4194 | // to "spec_block_die_offset" | |||
4195 | for (DWARFDIE child_die = die.GetFirstChild(); child_die; child_die = child_die.GetSibling()) | |||
4196 | { | |||
4197 | DWARFDIE result_die = FindBlockContainingSpecification (child_die, spec_block_die_offset); | |||
4198 | if (result_die) | |||
4199 | return result_die; | |||
4200 | } | |||
4201 | } | |||
4202 | ||||
4203 | return DWARFDIE(); | |||
4204 | } | |||
4205 | ||||
4206 | size_t | |||
4207 | SymbolFileDWARF::ParseVariables (const SymbolContext& sc, | |||
4208 | const DWARFDIE &orig_die, | |||
4209 | const lldb::addr_t func_low_pc, | |||
4210 | bool parse_siblings, | |||
4211 | bool parse_children, | |||
4212 | VariableList* cc_variable_list) | |||
4213 | { | |||
4214 | if (!orig_die) | |||
4215 | return 0; | |||
4216 | ||||
4217 | VariableListSP variable_list_sp; | |||
4218 | ||||
4219 | size_t vars_added = 0; | |||
4220 | DWARFDIE die = orig_die; | |||
4221 | while (die) | |||
4222 | { | |||
4223 | dw_tag_t tag = die.Tag(); | |||
4224 | ||||
4225 | // Check to see if we have already parsed this variable or constant? | |||
4226 | VariableSP var_sp = GetDIEToVariable()[die.GetDIE()]; | |||
4227 | if (var_sp) | |||
4228 | { | |||
4229 | if (cc_variable_list) | |||
4230 | cc_variable_list->AddVariableIfUnique (var_sp); | |||
4231 | } | |||
4232 | else | |||
4233 | { | |||
4234 | // We haven't already parsed it, lets do that now. | |||
4235 | if ((tag == DW_TAG_variable) || | |||
4236 | (tag == DW_TAG_constant) || | |||
4237 | (tag == DW_TAG_formal_parameter && sc.function)) | |||
4238 | { | |||
4239 | if (variable_list_sp.get() == NULL__null) | |||
4240 | { | |||
4241 | DWARFDIE sc_parent_die = GetParentSymbolContextDIE(orig_die); | |||
4242 | dw_tag_t parent_tag = sc_parent_die.Tag(); | |||
4243 | switch (parent_tag) | |||
4244 | { | |||
4245 | case DW_TAG_compile_unit: | |||
4246 | if (sc.comp_unit != NULL__null) | |||
4247 | { | |||
4248 | variable_list_sp = sc.comp_unit->GetVariableList(false); | |||
4249 | if (variable_list_sp.get() == NULL__null) | |||
4250 | { | |||
4251 | variable_list_sp.reset(new VariableList()); | |||
4252 | sc.comp_unit->SetVariableList(variable_list_sp); | |||
4253 | } | |||
4254 | } | |||
4255 | else | |||
4256 | { | |||
4257 | GetObjectFile()->GetModule()->ReportError ("parent 0x%8.8" PRIx64"l" "x" " %s with no valid compile unit in symbol context for 0x%8.8" PRIx64"l" "x" " %s.\n", | |||
4258 | sc_parent_die.GetID(), | |||
4259 | sc_parent_die.GetTagAsCString(), | |||
4260 | orig_die.GetID(), | |||
4261 | orig_die.GetTagAsCString()); | |||
4262 | } | |||
4263 | break; | |||
4264 | ||||
4265 | case DW_TAG_subprogram: | |||
4266 | case DW_TAG_inlined_subroutine: | |||
4267 | case DW_TAG_lexical_block: | |||
4268 | if (sc.function != NULL__null) | |||
4269 | { | |||
4270 | // Check to see if we already have parsed the variables for the given scope | |||
4271 | ||||
4272 | Block *block = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); | |||
4273 | if (block == NULL__null) | |||
4274 | { | |||
4275 | // This must be a specification or abstract origin with | |||
4276 | // a concrete block counterpart in the current function. We need | |||
4277 | // to find the concrete block so we can correctly add the | |||
4278 | // variable to it | |||
4279 | const DWARFDIE concrete_block_die = FindBlockContainingSpecification (DIERef(sc.function->GetID()), | |||
4280 | sc_parent_die.GetOffset()); | |||
4281 | if (concrete_block_die) | |||
4282 | block = sc.function->GetBlock(true).FindBlockByID(concrete_block_die.GetID()); | |||
4283 | } | |||
4284 | ||||
4285 | if (block != NULL__null) | |||
4286 | { | |||
4287 | const bool can_create = false; | |||
4288 | variable_list_sp = block->GetBlockVariableList (can_create); | |||
4289 | if (variable_list_sp.get() == NULL__null) | |||
4290 | { | |||
4291 | variable_list_sp.reset(new VariableList()); | |||
4292 | block->SetVariableList(variable_list_sp); | |||
4293 | } | |||
4294 | } | |||
4295 | } | |||
4296 | break; | |||
4297 | ||||
4298 | default: | |||
4299 | GetObjectFile()->GetModule()->ReportError ("didn't find appropriate parent DIE for variable list for 0x%8.8" PRIx64"l" "x" " %s.\n", | |||
4300 | orig_die.GetID(), | |||
4301 | orig_die.GetTagAsCString()); | |||
4302 | break; | |||
4303 | } | |||
4304 | } | |||
4305 | ||||
4306 | if (variable_list_sp) | |||
4307 | { | |||
4308 | VariableSP var_sp (ParseVariableDIE(sc, die, func_low_pc)); | |||
4309 | if (var_sp) | |||
4310 | { | |||
4311 | variable_list_sp->AddVariableIfUnique (var_sp); | |||
4312 | if (cc_variable_list) | |||
4313 | cc_variable_list->AddVariableIfUnique (var_sp); | |||
4314 | ++vars_added; | |||
4315 | } | |||
4316 | } | |||
4317 | } | |||
4318 | } | |||
4319 | ||||
4320 | bool skip_children = (sc.function == NULL__null && tag == DW_TAG_subprogram); | |||
4321 | ||||
4322 | if (!skip_children && parse_children && die.HasChildren()) | |||
4323 | { | |||
4324 | vars_added += ParseVariables(sc, die.GetFirstChild(), func_low_pc, true, true, cc_variable_list); | |||
4325 | } | |||
4326 | ||||
4327 | if (parse_siblings) | |||
4328 | die = die.GetSibling(); | |||
4329 | else | |||
4330 | die.Clear(); | |||
4331 | } | |||
4332 | return vars_added; | |||
4333 | } | |||
4334 | ||||
4335 | //------------------------------------------------------------------ | |||
4336 | // PluginInterface protocol | |||
4337 | //------------------------------------------------------------------ | |||
4338 | ConstString | |||
4339 | SymbolFileDWARF::GetPluginName() | |||
4340 | { | |||
4341 | return GetPluginNameStatic(); | |||
4342 | } | |||
4343 | ||||
4344 | uint32_t | |||
4345 | SymbolFileDWARF::GetPluginVersion() | |||
4346 | { | |||
4347 | return 1; | |||
4348 | } | |||
4349 | ||||
4350 | void | |||
4351 | SymbolFileDWARF::DumpIndexes () | |||
4352 | { | |||
4353 | StreamFile s(stdoutstdout, false); | |||
4354 | ||||
4355 | s.Printf ("DWARF index for (%s) '%s':", | |||
4356 | GetObjectFile()->GetModule()->GetArchitecture().GetArchitectureName(), | |||
4357 | GetObjectFile()->GetFileSpec().GetPath().c_str()); | |||
4358 | s.Printf("\nFunction basenames:\n"); m_function_basename_index.Dump (&s); | |||
4359 | s.Printf("\nFunction fullnames:\n"); m_function_fullname_index.Dump (&s); | |||
4360 | s.Printf("\nFunction methods:\n"); m_function_method_index.Dump (&s); | |||
4361 | s.Printf("\nFunction selectors:\n"); m_function_selector_index.Dump (&s); | |||
4362 | s.Printf("\nObjective C class selectors:\n"); m_objc_class_selectors_index.Dump (&s); | |||
4363 | s.Printf("\nGlobals and statics:\n"); m_global_index.Dump (&s); | |||
4364 | s.Printf("\nTypes:\n"); m_type_index.Dump (&s); | |||
4365 | s.Printf("\nNamespaces:\n"); m_namespace_index.Dump (&s); | |||
4366 | } | |||
4367 | ||||
4368 | ||||
4369 | SymbolFileDWARFDebugMap * | |||
4370 | SymbolFileDWARF::GetDebugMapSymfile () | |||
4371 | { | |||
4372 | if (m_debug_map_symfile == NULL__null && !m_debug_map_module_wp.expired()) | |||
4373 | { | |||
4374 | lldb::ModuleSP module_sp (m_debug_map_module_wp.lock()); | |||
4375 | if (module_sp) | |||
4376 | { | |||
4377 | SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); | |||
4378 | if (sym_vendor) | |||
4379 | m_debug_map_symfile = (SymbolFileDWARFDebugMap *)sym_vendor->GetSymbolFile(); | |||
4380 | } | |||
4381 | } | |||
4382 | return m_debug_map_symfile; | |||
4383 | } | |||
4384 | ||||
4385 | DWARFExpression::LocationListFormat | |||
4386 | SymbolFileDWARF::GetLocationListFormat() const | |||
4387 | { | |||
4388 | return DWARFExpression::RegularLocationList; | |||
4389 | } |