Bug Summary

File:tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Warning:line 67, column 29
Use of memory after it is freed

Annotated Source Code

[?] Use j/k keys for keyboard navigation

/build/llvm-toolchain-snapshot-6.0~svn321639/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

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

/usr/lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/shared_ptr.h

1// shared_ptr and weak_ptr implementation -*- C++ -*-
2
3// Copyright (C) 2007-2017 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25// GCC Note: Based on files from version 1.32.0 of the Boost library.
26
27// shared_count.hpp
28// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29
30// shared_ptr.hpp
31// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32// Copyright (C) 2001, 2002, 2003 Peter Dimov
33
34// weak_ptr.hpp
35// Copyright (C) 2001, 2002, 2003 Peter Dimov
36
37// enable_shared_from_this.hpp
38// Copyright (C) 2002 Peter Dimov
39
40// Distributed under the Boost Software License, Version 1.0. (See
41// accompanying file LICENSE_1_0.txt or copy at
42// http://www.boost.org/LICENSE_1_0.txt)
43
44/** @file
45 * This is an internal header file, included by other library headers.
46 * Do not attempt to use it directly. @headername{memory}
47 */
48
49#ifndef _SHARED_PTR_H1
50#define _SHARED_PTR_H1 1
51
52#include <bits/shared_ptr_base.h>
53
54namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
55{
56_GLIBCXX_BEGIN_NAMESPACE_VERSION
57
58 /**
59 * @addtogroup pointer_abstractions
60 * @{
61 */
62
63 /// 20.7.2.2.11 shared_ptr I/O
64 template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
65 inline std::basic_ostream<_Ch, _Tr>&
66 operator<<(std::basic_ostream<_Ch, _Tr>& __os,
67 const __shared_ptr<_Tp, _Lp>& __p)
68 {
69 __os << __p.get();
70 return __os;
71 }
72
73 /// 20.7.2.2.10 shared_ptr get_deleter
74 template<typename _Del, typename _Tp, _Lock_policy _Lp>
75 inline _Del*
76 get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept
77 {
78#if __cpp_rtti199711
79 return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
80#else
81 return 0;
82#endif
83 }
84
85
86 /**
87 * @brief A smart pointer with reference-counted copy semantics.
88 *
89 * The object pointed to is deleted when the last shared_ptr pointing to
90 * it is destroyed or reset.
91 */
92 template<typename _Tp>
93 class shared_ptr : public __shared_ptr<_Tp>
94 {
95 template<typename... _Args>
96 using _Constructible = typename enable_if<
97 is_constructible<__shared_ptr<_Tp>, _Args...>::value
98 >::type;
99
100 template<typename _Arg>
101 using _Assignable = typename enable_if<
102 is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&
103 >::type;
104
105 public:
106
107 using element_type = typename __shared_ptr<_Tp>::element_type;
108
109#if __cplusplus201103L > 201402L
110# define __cpp_lib_shared_ptr_weak_type 201606
111 using weak_type = weak_ptr<_Tp>;
112#endif
113 /**
114 * @brief Construct an empty %shared_ptr.
115 * @post use_count()==0 && get()==0
116 */
117 constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }
118
119 shared_ptr(const shared_ptr&) noexcept = default;
120
121 /**
122 * @brief Construct a %shared_ptr that owns the pointer @a __p.
123 * @param __p A pointer that is convertible to element_type*.
124 * @post use_count() == 1 && get() == __p
125 * @throw std::bad_alloc, in which case @c delete @a __p is called.
126 */
127 template<typename _Yp, typename = _Constructible<_Yp*>>
128 explicit
129 shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
130
131 /**
132 * @brief Construct a %shared_ptr that owns the pointer @a __p
133 * and the deleter @a __d.
134 * @param __p A pointer.
135 * @param __d A deleter.
136 * @post use_count() == 1 && get() == __p
137 * @throw std::bad_alloc, in which case @a __d(__p) is called.
138 *
139 * Requirements: _Deleter's copy constructor and destructor must
140 * not throw
141 *
142 * __shared_ptr will release __p by calling __d(__p)
143 */
144 template<typename _Yp, typename _Deleter,
145 typename = _Constructible<_Yp*, _Deleter>>
146 shared_ptr(_Yp* __p, _Deleter __d)
147 : __shared_ptr<_Tp>(__p, std::move(__d)) { }
148
149 /**
150 * @brief Construct a %shared_ptr that owns a null pointer
151 * and the deleter @a __d.
152 * @param __p A null pointer constant.
153 * @param __d A deleter.
154 * @post use_count() == 1 && get() == __p
155 * @throw std::bad_alloc, in which case @a __d(__p) is called.
156 *
157 * Requirements: _Deleter's copy constructor and destructor must
158 * not throw
159 *
160 * The last owner will call __d(__p)
161 */
162 template<typename _Deleter>
163 shared_ptr(nullptr_t __p, _Deleter __d)
164 : __shared_ptr<_Tp>(__p, std::move(__d)) { }
165
166 /**
167 * @brief Construct a %shared_ptr that owns the pointer @a __p
168 * and the deleter @a __d.
169 * @param __p A pointer.
170 * @param __d A deleter.
171 * @param __a An allocator.
172 * @post use_count() == 1 && get() == __p
173 * @throw std::bad_alloc, in which case @a __d(__p) is called.
174 *
175 * Requirements: _Deleter's copy constructor and destructor must
176 * not throw _Alloc's copy constructor and destructor must not
177 * throw.
178 *
179 * __shared_ptr will release __p by calling __d(__p)
180 */
181 template<typename _Yp, typename _Deleter, typename _Alloc,
182 typename = _Constructible<_Yp*, _Deleter, _Alloc>>
183 shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
184 : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
185
186 /**
187 * @brief Construct a %shared_ptr that owns a null pointer
188 * and the deleter @a __d.
189 * @param __p A null pointer constant.
190 * @param __d A deleter.
191 * @param __a An allocator.
192 * @post use_count() == 1 && get() == __p
193 * @throw std::bad_alloc, in which case @a __d(__p) is called.
194 *
195 * Requirements: _Deleter's copy constructor and destructor must
196 * not throw _Alloc's copy constructor and destructor must not
197 * throw.
198 *
199 * The last owner will call __d(__p)
200 */
201 template<typename _Deleter, typename _Alloc>
202 shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
203 : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
204
205 // Aliasing constructor
206
207 /**
208 * @brief Constructs a %shared_ptr instance that stores @a __p
209 * and shares ownership with @a __r.
210 * @param __r A %shared_ptr.
211 * @param __p A pointer that will remain valid while @a *__r is valid.
212 * @post get() == __p && use_count() == __r.use_count()
213 *
214 * This can be used to construct a @c shared_ptr to a sub-object
215 * of an object managed by an existing @c shared_ptr.
216 *
217 * @code
218 * shared_ptr< pair<int,int> > pii(new pair<int,int>());
219 * shared_ptr<int> pi(pii, &pii->first);
220 * assert(pii.use_count() == 2);
221 * @endcode
222 */
223 template<typename _Yp>
224 shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
225 : __shared_ptr<_Tp>(__r, __p) { }
226
227 /**
228 * @brief If @a __r is empty, constructs an empty %shared_ptr;
229 * otherwise construct a %shared_ptr that shares ownership
230 * with @a __r.
231 * @param __r A %shared_ptr.
232 * @post get() == __r.get() && use_count() == __r.use_count()
233 */
234 template<typename _Yp,
235 typename = _Constructible<const shared_ptr<_Yp>&>>
236 shared_ptr(const shared_ptr<_Yp>& __r) noexcept
237 : __shared_ptr<_Tp>(__r) { }
238
239 /**
240 * @brief Move-constructs a %shared_ptr instance from @a __r.
241 * @param __r A %shared_ptr rvalue.
242 * @post *this contains the old value of @a __r, @a __r is empty.
243 */
244 shared_ptr(shared_ptr&& __r) noexcept
245 : __shared_ptr<_Tp>(std::move(__r)) { }
246
247 /**
248 * @brief Move-constructs a %shared_ptr instance from @a __r.
249 * @param __r A %shared_ptr rvalue.
250 * @post *this contains the old value of @a __r, @a __r is empty.
251 */
252 template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>>
253 shared_ptr(shared_ptr<_Yp>&& __r) noexcept
254 : __shared_ptr<_Tp>(std::move(__r)) { }
255
256 /**
257 * @brief Constructs a %shared_ptr that shares ownership with @a __r
258 * and stores a copy of the pointer stored in @a __r.
259 * @param __r A weak_ptr.
260 * @post use_count() == __r.use_count()
261 * @throw bad_weak_ptr when __r.expired(),
262 * in which case the constructor has no effect.
263 */
264 template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
265 explicit shared_ptr(const weak_ptr<_Yp>& __r)
266 : __shared_ptr<_Tp>(__r) { }
267
268#if _GLIBCXX_USE_DEPRECATED1
269 template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>>
270 shared_ptr(auto_ptr<_Yp>&& __r);
271#endif
272
273 // _GLIBCXX_RESOLVE_LIB_DEFECTS
274 // 2399. shared_ptr's constructor from unique_ptr should be constrained
275 template<typename _Yp, typename _Del,
276 typename = _Constructible<unique_ptr<_Yp, _Del>>>
277 shared_ptr(unique_ptr<_Yp, _Del>&& __r)
278 : __shared_ptr<_Tp>(std::move(__r)) { }
279
280#if __cplusplus201103L <= 201402L && _GLIBCXX_USE_DEPRECATED1
281 // This non-standard constructor exists to support conversions that
282 // were possible in C++11 and C++14 but are ill-formed in C++17.
283 // If an exception is thrown this constructor has no effect.
284 template<typename _Yp, typename _Del,
285 _Constructible<unique_ptr<_Yp, _Del>, __sp_array_delete>* = 0>
286 shared_ptr(unique_ptr<_Yp, _Del>&& __r)
287 : __shared_ptr<_Tp>(std::move(__r), __sp_array_delete()) { }
288#endif
289
290 /**
291 * @brief Construct an empty %shared_ptr.
292 * @post use_count() == 0 && get() == nullptr
293 */
294 constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
295
296 shared_ptr& operator=(const shared_ptr&) noexcept = default;
36
Calling defaulted copy assignment operator for '__shared_ptr'
51
Returning; memory was released
64
Calling defaulted copy assignment operator for '__shared_ptr'
297
298 template<typename _Yp>
299 _Assignable<const shared_ptr<_Yp>&>
300 operator=(const shared_ptr<_Yp>& __r) noexcept
301 {
302 this->__shared_ptr<_Tp>::operator=(__r);
303 return *this;
304 }
305
306#if _GLIBCXX_USE_DEPRECATED1
307 template<typename _Yp>
308 _Assignable<auto_ptr<_Yp>>
309 operator=(auto_ptr<_Yp>&& __r)
310 {
311 this->__shared_ptr<_Tp>::operator=(std::move(__r));
312 return *this;
313 }
314#endif
315
316 shared_ptr&
317 operator=(shared_ptr&& __r) noexcept
318 {
319 this->__shared_ptr<_Tp>::operator=(std::move(__r));
320 return *this;
321 }
322
323 template<class _Yp>
324 _Assignable<shared_ptr<_Yp>>
325 operator=(shared_ptr<_Yp>&& __r) noexcept
326 {
327 this->__shared_ptr<_Tp>::operator=(std::move(__r));
328 return *this;
329 }
330
331 template<typename _Yp, typename _Del>
332 _Assignable<unique_ptr<_Yp, _Del>>
333 operator=(unique_ptr<_Yp, _Del>&& __r)
334 {
335 this->__shared_ptr<_Tp>::operator=(std::move(__r));
336 return *this;
337 }
338
339 private:
340 // This constructor is non-standard, it is used by allocate_shared.
341 template<typename _Alloc, typename... _Args>
342 shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
343 _Args&&... __args)
344 : __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...)
345 { }
346
347 template<typename _Yp, typename _Alloc, typename... _Args>
348 friend shared_ptr<_Yp>
349 allocate_shared(const _Alloc& __a, _Args&&... __args);
350
351 // This constructor is non-standard, it is used by weak_ptr::lock().
352 shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
353 : __shared_ptr<_Tp>(__r, std::nothrow) { }
354
355 friend class weak_ptr<_Tp>;
356 };
357
358#if __cpp_deduction_guides >= 201606
359 template<typename _Tp>
360 shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>;
361 template<typename _Tp, typename _Del>
362 shared_ptr(unique_ptr<_Tp, _Del>) -> shared_ptr<_Tp>;
363#endif
364
365 // 20.7.2.2.7 shared_ptr comparisons
366 template<typename _Tp, typename _Up>
367 inline bool
368 operator==(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
369 { return __a.get() == __b.get(); }
370
371 template<typename _Tp>
372 inline bool
373 operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
374 { return !__a; }
375
376 template<typename _Tp>
377 inline bool
378 operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
379 { return !__a; }
380
381 template<typename _Tp, typename _Up>
382 inline bool
383 operator!=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
384 { return __a.get() != __b.get(); }
385
386 template<typename _Tp>
387 inline bool
388 operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
389 { return (bool)__a; }
390
391 template<typename _Tp>
392 inline bool
393 operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
394 { return (bool)__a; }
395
396 template<typename _Tp, typename _Up>
397 inline bool
398 operator<(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
399 {
400 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
401 using _Up_elt = typename shared_ptr<_Up>::element_type;
402 using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
403 return less<_Vp>()(__a.get(), __b.get());
404 }
405
406 template<typename _Tp>
407 inline bool
408 operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
409 {
410 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
411 return less<_Tp_elt*>()(__a.get(), nullptr);
412 }
413
414 template<typename _Tp>
415 inline bool
416 operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
417 {
418 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
419 return less<_Tp_elt*>()(nullptr, __a.get());
420 }
421
422 template<typename _Tp, typename _Up>
423 inline bool
424 operator<=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
425 { return !(__b < __a); }
426
427 template<typename _Tp>
428 inline bool
429 operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
430 { return !(nullptr < __a); }
431
432 template<typename _Tp>
433 inline bool
434 operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
435 { return !(__a < nullptr); }
436
437 template<typename _Tp, typename _Up>
438 inline bool
439 operator>(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
440 { return (__b < __a); }
441
442 template<typename _Tp>
443 inline bool
444 operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
445 { return nullptr < __a; }
446
447 template<typename _Tp>
448 inline bool
449 operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
450 { return __a < nullptr; }
451
452 template<typename _Tp, typename _Up>
453 inline bool
454 operator>=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
455 { return !(__a < __b); }
456
457 template<typename _Tp>
458 inline bool
459 operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
460 { return !(__a < nullptr); }
461
462 template<typename _Tp>
463 inline bool
464 operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
465 { return !(nullptr < __a); }
466
467 template<typename _Tp>
468 struct less<shared_ptr<_Tp>> : public _Sp_less<shared_ptr<_Tp>>
469 { };
470
471 // 20.7.2.2.8 shared_ptr specialized algorithms.
472 template<typename _Tp>
473 inline void
474 swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
475 { __a.swap(__b); }
476
477 // 20.7.2.2.9 shared_ptr casts.
478 template<typename _Tp, typename _Up>
479 inline shared_ptr<_Tp>
480 static_pointer_cast(const shared_ptr<_Up>& __r) noexcept
481 {
482 using _Sp = shared_ptr<_Tp>;
483 return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
484 }
485
486 template<typename _Tp, typename _Up>
487 inline shared_ptr<_Tp>
488 const_pointer_cast(const shared_ptr<_Up>& __r) noexcept
489 {
490 using _Sp = shared_ptr<_Tp>;
491 return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
492 }
493
494 template<typename _Tp, typename _Up>
495 inline shared_ptr<_Tp>
496 dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept
497 {
498 using _Sp = shared_ptr<_Tp>;
499 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
500 return _Sp(__r, __p);
501 return _Sp();
502 }
503
504#if __cplusplus201103L > 201402L
505 template<typename _Tp, typename _Up>
506 inline shared_ptr<_Tp>
507 reinterpret_pointer_cast(const shared_ptr<_Up>& __r) noexcept
508 {
509 using _Sp = shared_ptr<_Tp>;
510 return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
511 }
512#endif
513
514 /**
515 * @brief A smart pointer with weak semantics.
516 *
517 * With forwarding constructors and assignment operators.
518 */
519 template<typename _Tp>
520 class weak_ptr : public __weak_ptr<_Tp>
521 {
522 template<typename _Arg>
523 using _Constructible = typename enable_if<
524 is_constructible<__weak_ptr<_Tp>, _Arg>::value
525 >::type;
526
527 template<typename _Arg>
528 using _Assignable = typename enable_if<
529 is_assignable<__weak_ptr<_Tp>&, _Arg>::value, weak_ptr&
530 >::type;
531
532 public:
533 constexpr weak_ptr() noexcept = default;
534
535 template<typename _Yp,
536 typename = _Constructible<const shared_ptr<_Yp>&>>
537 weak_ptr(const shared_ptr<_Yp>& __r) noexcept
538 : __weak_ptr<_Tp>(__r) { }
539
540 weak_ptr(const weak_ptr&) noexcept = default;
541
542 template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
543 weak_ptr(const weak_ptr<_Yp>& __r) noexcept
544 : __weak_ptr<_Tp>(__r) { }
545
546 weak_ptr(weak_ptr&&) noexcept = default;
547
548 template<typename _Yp, typename = _Constructible<weak_ptr<_Yp>>>
549 weak_ptr(weak_ptr<_Yp>&& __r) noexcept
550 : __weak_ptr<_Tp>(std::move(__r)) { }
551
552 weak_ptr&
553 operator=(const weak_ptr& __r) noexcept = default;
554
555 template<typename _Yp>
556 _Assignable<const weak_ptr<_Yp>&>
557 operator=(const weak_ptr<_Yp>& __r) noexcept
558 {
559 this->__weak_ptr<_Tp>::operator=(__r);
560 return *this;
561 }
562
563 template<typename _Yp>
564 _Assignable<const shared_ptr<_Yp>&>
565 operator=(const shared_ptr<_Yp>& __r) noexcept
566 {
567 this->__weak_ptr<_Tp>::operator=(__r);
568 return *this;
569 }
570
571 weak_ptr&
572 operator=(weak_ptr&& __r) noexcept = default;
573
574 template<typename _Yp>
575 _Assignable<weak_ptr<_Yp>>
576 operator=(weak_ptr<_Yp>&& __r) noexcept
577 {
578 this->__weak_ptr<_Tp>::operator=(std::move(__r));
579 return *this;
580 }
581
582 shared_ptr<_Tp>
583 lock() const noexcept
584 { return shared_ptr<_Tp>(*this, std::nothrow); }
585 };
586
587#if __cpp_deduction_guides >= 201606
588 template<typename _Tp>
589 weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>;
590#endif
591
592 // 20.7.2.3.6 weak_ptr specialized algorithms.
593 template<typename _Tp>
594 inline void
595 swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
596 { __a.swap(__b); }
597
598
599 /// Primary template owner_less
600 template<typename _Tp = void>
601 struct owner_less;
602
603 /// Void specialization of owner_less
604 template<>
605 struct owner_less<void> : _Sp_owner_less<void, void>
606 { };
607
608 /// Partial specialization of owner_less for shared_ptr.
609 template<typename _Tp>
610 struct owner_less<shared_ptr<_Tp>>
611 : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>>
612 { };
613
614 /// Partial specialization of owner_less for weak_ptr.
615 template<typename _Tp>
616 struct owner_less<weak_ptr<_Tp>>
617 : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
618 { };
619
620 /**
621 * @brief Base class allowing use of member function shared_from_this.
622 */
623 template<typename _Tp>
624 class enable_shared_from_this
625 {
626 protected:
627 constexpr enable_shared_from_this() noexcept { }
628
629 enable_shared_from_this(const enable_shared_from_this&) noexcept { }
630
631 enable_shared_from_this&
632 operator=(const enable_shared_from_this&) noexcept
633 { return *this; }
634
635 ~enable_shared_from_this() { }
636
637 public:
638 shared_ptr<_Tp>
639 shared_from_this()
640 { return shared_ptr<_Tp>(this->_M_weak_this); }
641
642 shared_ptr<const _Tp>
643 shared_from_this() const
644 { return shared_ptr<const _Tp>(this->_M_weak_this); }
645
646#if __cplusplus201103L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
647#define __cpp_lib_enable_shared_from_this 201603
648 weak_ptr<_Tp>
649 weak_from_this() noexcept
650 { return this->_M_weak_this; }
651
652 weak_ptr<const _Tp>
653 weak_from_this() const noexcept
654 { return this->_M_weak_this; }
655#endif
656
657 private:
658 template<typename _Tp1>
659 void
660 _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
661 { _M_weak_this._M_assign(__p, __n); }
662
663 // Found by ADL when this is an associated class.
664 friend const enable_shared_from_this*
665 __enable_shared_from_this_base(const __shared_count<>&,
666 const enable_shared_from_this* __p)
667 { return __p; }
668
669 template<typename, _Lock_policy>
670 friend class __shared_ptr;
671
672 mutable weak_ptr<_Tp> _M_weak_this;
673 };
674
675 /**
676 * @brief Create an object that is owned by a shared_ptr.
677 * @param __a An allocator.
678 * @param __args Arguments for the @a _Tp object's constructor.
679 * @return A shared_ptr that owns the newly created object.
680 * @throw An exception thrown from @a _Alloc::allocate or from the
681 * constructor of @a _Tp.
682 *
683 * A copy of @a __a will be used to allocate memory for the shared_ptr
684 * and the new object.
685 */
686 template<typename _Tp, typename _Alloc, typename... _Args>
687 inline shared_ptr<_Tp>
688 allocate_shared(const _Alloc& __a, _Args&&... __args)
689 {
690 return shared_ptr<_Tp>(_Sp_make_shared_tag(), __a,
691 std::forward<_Args>(__args)...);
692 }
693
694 /**
695 * @brief Create an object that is owned by a shared_ptr.
696 * @param __args Arguments for the @a _Tp object's constructor.
697 * @return A shared_ptr that owns the newly created object.
698 * @throw std::bad_alloc, or an exception thrown from the
699 * constructor of @a _Tp.
700 */
701 template<typename _Tp, typename... _Args>
702 inline shared_ptr<_Tp>
703 make_shared(_Args&&... __args)
704 {
705 typedef typename std::remove_const<_Tp>::type _Tp_nc;
706 return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
707 std::forward<_Args>(__args)...);
708 }
709
710 /// std::hash specialization for shared_ptr.
711 template<typename _Tp>
712 struct hash<shared_ptr<_Tp>>
713 : public __hash_base<size_t, shared_ptr<_Tp>>
714 {
715 size_t
716 operator()(const shared_ptr<_Tp>& __s) const noexcept
717 {
718 return std::hash<typename shared_ptr<_Tp>::element_type*>()(__s.get());
719 }
720 };
721
722 // @} group pointer_abstractions
723
724_GLIBCXX_END_NAMESPACE_VERSION
725} // namespace
726
727#endif // _SHARED_PTR_H

/usr/lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/shared_ptr_base.h

1// shared_ptr and weak_ptr implementation details -*- C++ -*-
2
3// Copyright (C) 2007-2017 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25// GCC Note: Based on files from version 1.32.0 of the Boost library.
26
27// shared_count.hpp
28// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29
30// shared_ptr.hpp
31// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32// Copyright (C) 2001, 2002, 2003 Peter Dimov
33
34// weak_ptr.hpp
35// Copyright (C) 2001, 2002, 2003 Peter Dimov
36
37// enable_shared_from_this.hpp
38// Copyright (C) 2002 Peter Dimov
39
40// Distributed under the Boost Software License, Version 1.0. (See
41// accompanying file LICENSE_1_0.txt or copy at
42// http://www.boost.org/LICENSE_1_0.txt)
43
44/** @file bits/shared_ptr_base.h
45 * This is an internal header file, included by other library headers.
46 * Do not attempt to use it directly. @headername{memory}
47 */
48
49#ifndef _SHARED_PTR_BASE_H1
50#define _SHARED_PTR_BASE_H1 1
51
52#if __cpp_rtti199711
53# include <typeinfo>
54#endif
55#include <bits/allocated_ptr.h>
56#include <bits/refwrap.h>
57#include <bits/stl_function.h>
58#include <ext/aligned_buffer.h>
59
60namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
61{
62_GLIBCXX_BEGIN_NAMESPACE_VERSION
63
64#if _GLIBCXX_USE_DEPRECATED1
65 template<typename> class auto_ptr;
66#endif
67
68 /**
69 * @brief Exception possibly thrown by @c shared_ptr.
70 * @ingroup exceptions
71 */
72 class bad_weak_ptr : public std::exception
73 {
74 public:
75 virtual char const* what() const noexcept;
76
77 virtual ~bad_weak_ptr() noexcept;
78 };
79
80 // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
81 inline void
82 __throw_bad_weak_ptr()
83 { _GLIBCXX_THROW_OR_ABORT(bad_weak_ptr())(__builtin_abort()); }
84
85 using __gnu_cxx::_Lock_policy;
86 using __gnu_cxx::__default_lock_policy;
87 using __gnu_cxx::_S_single;
88 using __gnu_cxx::_S_mutex;
89 using __gnu_cxx::_S_atomic;
90
91 // Empty helper class except when the template argument is _S_mutex.
92 template<_Lock_policy _Lp>
93 class _Mutex_base
94 {
95 protected:
96 // The atomic policy uses fully-fenced builtins, single doesn't care.
97 enum { _S_need_barriers = 0 };
98 };
99
100 template<>
101 class _Mutex_base<_S_mutex>
102 : public __gnu_cxx::__mutex
103 {
104 protected:
105 // This policy is used when atomic builtins are not available.
106 // The replacement atomic operations might not have the necessary
107 // memory barriers.
108 enum { _S_need_barriers = 1 };
109 };
110
111 template<_Lock_policy _Lp = __default_lock_policy>
112 class _Sp_counted_base
113 : public _Mutex_base<_Lp>
114 {
115 public:
116 _Sp_counted_base() noexcept
117 : _M_use_count(1), _M_weak_count(1) { }
118
119 virtual
120 ~_Sp_counted_base() noexcept
121 { }
122
123 // Called when _M_use_count drops to zero, to release the resources
124 // managed by *this.
125 virtual void
126 _M_dispose() noexcept = 0;
127
128 // Called when _M_weak_count drops to zero.
129 virtual void
130 _M_destroy() noexcept
131 { delete this; }
47
Memory is released
132
133 virtual void*
134 _M_get_deleter(const std::type_info&) noexcept = 0;
135
136 void
137 _M_add_ref_copy()
138 { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
139
140 void
141 _M_add_ref_lock();
142
143 bool
144 _M_add_ref_lock_nothrow();
145
146 void
147 _M_release() noexcept
148 {
149 // Be race-detector-friendly. For more info see bits/c++config.
150 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
151 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
42
Assuming the condition is true
43
Taking true branch
70
Calling '__exchange_and_add_dispatch'
152 {
153 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
154 _M_dispose();
155 // There must be a memory barrier between dispose() and destroy()
156 // to ensure that the effects of dispose() are observed in the
157 // thread that runs destroy().
158 // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
159 if (_Mutex_base<_Lp>::_S_need_barriers)
44
Taking false branch
160 {
161 __atomic_thread_fence (__ATOMIC_ACQ_REL4);
162 }
163
164 // Be race-detector-friendly. For more info see bits/c++config.
165 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
166 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
45
Taking true branch
167 -1) == 1)
168 {
169 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
170 _M_destroy();
46
Calling '_Sp_counted_base::_M_destroy'
48
Returning; memory was released
171 }
172 }
173 }
174
175 void
176 _M_weak_add_ref() noexcept
177 { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
178
179 void
180 _M_weak_release() noexcept
181 {
182 // Be race-detector-friendly. For more info see bits/c++config.
183 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
184 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
185 {
186 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
187 if (_Mutex_base<_Lp>::_S_need_barriers)
188 {
189 // See _M_release(),
190 // destroy() must observe results of dispose()
191 __atomic_thread_fence (__ATOMIC_ACQ_REL4);
192 }
193 _M_destroy();
194 }
195 }
196
197 long
198 _M_get_use_count() const noexcept
199 {
200 // No memory barrier is used here so there is no synchronization
201 // with other threads.
202 return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED0);
203 }
204
205 private:
206 _Sp_counted_base(_Sp_counted_base const&) = delete;
207 _Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
208
209 _Atomic_word _M_use_count; // #shared
210 _Atomic_word _M_weak_count; // #weak + (#shared != 0)
211 };
212
213 template<>
214 inline void
215 _Sp_counted_base<_S_single>::
216 _M_add_ref_lock()
217 {
218 if (_M_use_count == 0)
219 __throw_bad_weak_ptr();
220 ++_M_use_count;
221 }
222
223 template<>
224 inline void
225 _Sp_counted_base<_S_mutex>::
226 _M_add_ref_lock()
227 {
228 __gnu_cxx::__scoped_lock sentry(*this);
229 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
230 {
231 _M_use_count = 0;
232 __throw_bad_weak_ptr();
233 }
234 }
235
236 template<>
237 inline void
238 _Sp_counted_base<_S_atomic>::
239 _M_add_ref_lock()
240 {
241 // Perform lock-free add-if-not-zero operation.
242 _Atomic_word __count = _M_get_use_count();
243 do
244 {
245 if (__count == 0)
246 __throw_bad_weak_ptr();
247 // Replace the current counter value with the old value + 1, as
248 // long as it's not changed meanwhile.
249 }
250 while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
251 true, __ATOMIC_ACQ_REL4,
252 __ATOMIC_RELAXED0));
253 }
254
255 template<>
256 inline bool
257 _Sp_counted_base<_S_single>::
258 _M_add_ref_lock_nothrow()
259 {
260 if (_M_use_count == 0)
261 return false;
262 ++_M_use_count;
263 return true;
264 }
265
266 template<>
267 inline bool
268 _Sp_counted_base<_S_mutex>::
269 _M_add_ref_lock_nothrow()
270 {
271 __gnu_cxx::__scoped_lock sentry(*this);
272 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
273 {
274 _M_use_count = 0;
275 return false;
276 }
277 return true;
278 }
279
280 template<>
281 inline bool
282 _Sp_counted_base<_S_atomic>::
283 _M_add_ref_lock_nothrow()
284 {
285 // Perform lock-free add-if-not-zero operation.
286 _Atomic_word __count = _M_get_use_count();
287 do
288 {
289 if (__count == 0)
290 return false;
291 // Replace the current counter value with the old value + 1, as
292 // long as it's not changed meanwhile.
293 }
294 while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
295 true, __ATOMIC_ACQ_REL4,
296 __ATOMIC_RELAXED0));
297 return true;
298 }
299
300 template<>
301 inline void
302 _Sp_counted_base<_S_single>::_M_add_ref_copy()
303 { ++_M_use_count; }
304
305 template<>
306 inline void
307 _Sp_counted_base<_S_single>::_M_release() noexcept
308 {
309 if (--_M_use_count == 0)
310 {
311 _M_dispose();
312 if (--_M_weak_count == 0)
313 _M_destroy();
314 }
315 }
316
317 template<>
318 inline void
319 _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept
320 { ++_M_weak_count; }
321
322 template<>
323 inline void
324 _Sp_counted_base<_S_single>::_M_weak_release() noexcept
325 {
326 if (--_M_weak_count == 0)
327 _M_destroy();
328 }
329
330 template<>
331 inline long
332 _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept
333 { return _M_use_count; }
334
335
336 // Forward declarations.
337 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
338 class __shared_ptr;
339
340 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
341 class __weak_ptr;
342
343 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
344 class __enable_shared_from_this;
345
346 template<typename _Tp>
347 class shared_ptr;
348
349 template<typename _Tp>
350 class weak_ptr;
351
352 template<typename _Tp>
353 struct owner_less;
354
355 template<typename _Tp>
356 class enable_shared_from_this;
357
358 template<_Lock_policy _Lp = __default_lock_policy>
359 class __weak_count;
360
361 template<_Lock_policy _Lp = __default_lock_policy>
362 class __shared_count;
363
364
365 // Counted ptr with no deleter or allocator support
366 template<typename _Ptr, _Lock_policy _Lp>
367 class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>
368 {
369 public:
370 explicit
371 _Sp_counted_ptr(_Ptr __p) noexcept
372 : _M_ptr(__p) { }
373
374 virtual void
375 _M_dispose() noexcept
376 { delete _M_ptr; }
377
378 virtual void
379 _M_destroy() noexcept
380 { delete this; }
381
382 virtual void*
383 _M_get_deleter(const std::type_info&) noexcept
384 { return nullptr; }
385
386 _Sp_counted_ptr(const _Sp_counted_ptr&) = delete;
387 _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete;
388
389 private:
390 _Ptr _M_ptr;
391 };
392
393 template<>
394 inline void
395 _Sp_counted_ptr<nullptr_t, _S_single>::_M_dispose() noexcept { }
396
397 template<>
398 inline void
399 _Sp_counted_ptr<nullptr_t, _S_mutex>::_M_dispose() noexcept { }
400
401 template<>
402 inline void
403 _Sp_counted_ptr<nullptr_t, _S_atomic>::_M_dispose() noexcept { }
404
405 template<int _Nm, typename _Tp,
406 bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)>
407 struct _Sp_ebo_helper;
408
409 /// Specialization using EBO.
410 template<int _Nm, typename _Tp>
411 struct _Sp_ebo_helper<_Nm, _Tp, true> : private _Tp
412 {
413 explicit _Sp_ebo_helper(const _Tp& __tp) : _Tp(__tp) { }
414 explicit _Sp_ebo_helper(_Tp&& __tp) : _Tp(std::move(__tp)) { }
415
416 static _Tp&
417 _S_get(_Sp_ebo_helper& __eboh) { return static_cast<_Tp&>(__eboh); }
418 };
419
420 /// Specialization not using EBO.
421 template<int _Nm, typename _Tp>
422 struct _Sp_ebo_helper<_Nm, _Tp, false>
423 {
424 explicit _Sp_ebo_helper(const _Tp& __tp) : _M_tp(__tp) { }
425 explicit _Sp_ebo_helper(_Tp&& __tp) : _M_tp(std::move(__tp)) { }
426
427 static _Tp&
428 _S_get(_Sp_ebo_helper& __eboh)
429 { return __eboh._M_tp; }
430
431 private:
432 _Tp _M_tp;
433 };
434
435 // Support for custom deleter and/or allocator
436 template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>
437 class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>
438 {
439 class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc>
440 {
441 typedef _Sp_ebo_helper<0, _Deleter> _Del_base;
442 typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base;
443
444 public:
445 _Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
446 : _M_ptr(__p), _Del_base(std::move(__d)), _Alloc_base(__a)
447 { }
448
449 _Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); }
450 _Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); }
451
452 _Ptr _M_ptr;
453 };
454
455 public:
456 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>;
457
458 // __d(__p) must not throw.
459 _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept
460 : _M_impl(__p, std::move(__d), _Alloc()) { }
461
462 // __d(__p) must not throw.
463 _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
464 : _M_impl(__p, std::move(__d), __a) { }
465
466 ~_Sp_counted_deleter() noexcept { }
467
468 virtual void
469 _M_dispose() noexcept
470 { _M_impl._M_del()(_M_impl._M_ptr); }
471
472 virtual void
473 _M_destroy() noexcept
474 {
475 __allocator_type __a(_M_impl._M_alloc());
476 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
477 this->~_Sp_counted_deleter();
478 }
479
480 virtual void*
481 _M_get_deleter(const std::type_info& __ti) noexcept
482 {
483#if __cpp_rtti199711
484 // _GLIBCXX_RESOLVE_LIB_DEFECTS
485 // 2400. shared_ptr's get_deleter() should use addressof()
486 return __ti == typeid(_Deleter)
487 ? std::__addressof(_M_impl._M_del())
488 : nullptr;
489#else
490 return nullptr;
491#endif
492 }
493
494 private:
495 _Impl _M_impl;
496 };
497
498 // helpers for make_shared / allocate_shared
499
500 struct _Sp_make_shared_tag { };
501
502 template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
503 class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>
504 {
505 class _Impl : _Sp_ebo_helper<0, _Alloc>
506 {
507 typedef _Sp_ebo_helper<0, _Alloc> _A_base;
508
509 public:
510 explicit _Impl(_Alloc __a) noexcept : _A_base(__a) { }
511
512 _Alloc& _M_alloc() noexcept { return _A_base::_S_get(*this); }
513
514 __gnu_cxx::__aligned_buffer<_Tp> _M_storage;
515 };
516
517 public:
518 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>;
519
520 template<typename... _Args>
521 _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args)
522 : _M_impl(__a)
523 {
524 // _GLIBCXX_RESOLVE_LIB_DEFECTS
525 // 2070. allocate_shared should use allocator_traits<A>::construct
526 allocator_traits<_Alloc>::construct(__a, _M_ptr(),
527 std::forward<_Args>(__args)...); // might throw
528 }
529
530 ~_Sp_counted_ptr_inplace() noexcept { }
531
532 virtual void
533 _M_dispose() noexcept
534 {
535 allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr());
536 }
537
538 // Override because the allocator needs to know the dynamic type
539 virtual void
540 _M_destroy() noexcept
541 {
542 __allocator_type __a(_M_impl._M_alloc());
543 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
544 this->~_Sp_counted_ptr_inplace();
545 }
546
547 // Sneaky trick so __shared_ptr can get the managed pointer
548 virtual void*
549 _M_get_deleter(const std::type_info& __ti) noexcept
550 {
551#if __cpp_rtti199711
552 if (__ti == typeid(_Sp_make_shared_tag))
553 return const_cast<typename remove_cv<_Tp>::type*>(_M_ptr());
554#endif
555 return nullptr;
556 }
557
558 private:
559 _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }
560
561 _Impl _M_impl;
562 };
563
564 // The default deleter for shared_ptr<T[]> and shared_ptr<T[N]>.
565 struct __sp_array_delete
566 {
567 template<typename _Yp>
568 void operator()(_Yp* __p) const { delete[] __p; }
569 };
570
571 template<_Lock_policy _Lp>
572 class __shared_count
573 {
574 public:
575 constexpr __shared_count() noexcept : _M_pi(0)
576 { }
577
578 template<typename _Ptr>
579 explicit
580 __shared_count(_Ptr __p) : _M_pi(0)
581 {
582 __tryif (true)
583 {
584 _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
585 }
586 __catch(...)if (false)
587 {
588 delete __p;
589 __throw_exception_again;
590 }
591 }
592
593 template<typename _Ptr>
594 __shared_count(_Ptr __p, /* is_array = */ false_type)
595 : __shared_count(__p)
596 { }
597
598 template<typename _Ptr>
599 __shared_count(_Ptr __p, /* is_array = */ true_type)
600 : __shared_count(__p, __sp_array_delete{}, allocator<void>())
601 { }
602
603 template<typename _Ptr, typename _Deleter>
604 __shared_count(_Ptr __p, _Deleter __d)
605 : __shared_count(__p, std::move(__d), allocator<void>())
606 { }
607
608 template<typename _Ptr, typename _Deleter, typename _Alloc>
609 __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
610 {
611 typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
612 __tryif (true)
613 {
614 typename _Sp_cd_type::__allocator_type __a2(__a);
615 auto __guard = std::__allocate_guarded(__a2);
616 _Sp_cd_type* __mem = __guard.get();
617 ::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a));
618 _M_pi = __mem;
619 __guard = nullptr;
620 }
621 __catch(...)if (false)
622 {
623 __d(__p); // Call _Deleter on __p.
624 __throw_exception_again;
625 }
626 }
627
628 template<typename _Tp, typename _Alloc, typename... _Args>
629 __shared_count(_Sp_make_shared_tag, _Tp*, const _Alloc& __a,
630 _Args&&... __args)
631 : _M_pi(0)
632 {
633 typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;
634 typename _Sp_cp_type::__allocator_type __a2(__a);
635 auto __guard = std::__allocate_guarded(__a2);
636 _Sp_cp_type* __mem = __guard.get();
637 ::new (__mem) _Sp_cp_type(std::move(__a),
638 std::forward<_Args>(__args)...);
639 _M_pi = __mem;
640 __guard = nullptr;
641 }
642
643#if _GLIBCXX_USE_DEPRECATED1
644 // Special case for auto_ptr<_Tp> to provide the strong guarantee.
645 template<typename _Tp>
646 explicit
647 __shared_count(std::auto_ptr<_Tp>&& __r);
648#endif
649
650 // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.
651 template<typename _Tp, typename _Del>
652 explicit
653 __shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0)
654 {
655 // _GLIBCXX_RESOLVE_LIB_DEFECTS
656 // 2415. Inconsistency between unique_ptr and shared_ptr
657 if (__r.get() == nullptr)
658 return;
659
660 using _Ptr = typename unique_ptr<_Tp, _Del>::pointer;
661 using _Del2 = typename conditional<is_reference<_Del>::value,
662 reference_wrapper<typename remove_reference<_Del>::type>,
663 _Del>::type;
664 using _Sp_cd_type
665 = _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>;
666 using _Alloc = allocator<_Sp_cd_type>;
667 using _Alloc_traits = allocator_traits<_Alloc>;
668 _Alloc __a;
669 _Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1);
670 _Alloc_traits::construct(__a, __mem, __r.release(),
671 __r.get_deleter()); // non-throwing
672 _M_pi = __mem;
673 }
674
675 // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
676 explicit __shared_count(const __weak_count<_Lp>& __r);
677
678 // Does not throw if __r._M_get_use_count() == 0, caller must check.
679 explicit __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t);
680
681 ~__shared_count() noexcept
682 {
683 if (_M_pi != nullptr)
684 _M_pi->_M_release();
685 }
686
687 __shared_count(const __shared_count& __r) noexcept
688 : _M_pi(__r._M_pi)
689 {
690 if (_M_pi != 0)
691 _M_pi->_M_add_ref_copy();
692 }
693
694 __shared_count&
695 operator=(const __shared_count& __r) noexcept
696 {
697 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
698 if (__tmp != _M_pi)
38
Taking true branch
66
Taking true branch
699 {
700 if (__tmp != 0)
39
Taking false branch
67
Taking false branch
701 __tmp->_M_add_ref_copy();
702 if (_M_pi != 0)
40
Taking true branch
68
Taking true branch
703 _M_pi->_M_release();
41
Calling '_Sp_counted_base::_M_release'
49
Returning; memory was released
69
Calling '_Sp_counted_base::_M_release'
704 _M_pi = __tmp;
705 }
706 return *this;
707 }
708
709 void
710 _M_swap(__shared_count& __r) noexcept
711 {
712 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
713 __r._M_pi = _M_pi;
714 _M_pi = __tmp;
715 }
716
717 long
718 _M_get_use_count() const noexcept
719 { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
720
721 bool
722 _M_unique() const noexcept
723 { return this->_M_get_use_count() == 1; }
724
725 void*
726 _M_get_deleter(const std::type_info& __ti) const noexcept
727 { return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; }
728
729 bool
730 _M_less(const __shared_count& __rhs) const noexcept
731 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
732
733 bool
734 _M_less(const __weak_count<_Lp>& __rhs) const noexcept
735 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
736
737 // Friend function injected into enclosing namespace and found by ADL
738 friend inline bool
739 operator==(const __shared_count& __a, const __shared_count& __b) noexcept
740 { return __a._M_pi == __b._M_pi; }
741
742 private:
743 friend class __weak_count<_Lp>;
744
745 _Sp_counted_base<_Lp>* _M_pi;
746 };
747
748
749 template<_Lock_policy _Lp>
750 class __weak_count
751 {
752 public:
753 constexpr __weak_count() noexcept : _M_pi(nullptr)
754 { }
755
756 __weak_count(const __shared_count<_Lp>& __r) noexcept
757 : _M_pi(__r._M_pi)
758 {
759 if (_M_pi != nullptr)
760 _M_pi->_M_weak_add_ref();
761 }
762
763 __weak_count(const __weak_count& __r) noexcept
764 : _M_pi(__r._M_pi)
765 {
766 if (_M_pi != nullptr)
767 _M_pi->_M_weak_add_ref();
768 }
769
770 __weak_count(__weak_count&& __r) noexcept
771 : _M_pi(__r._M_pi)
772 { __r._M_pi = nullptr; }
773
774 ~__weak_count() noexcept
775 {
776 if (_M_pi != nullptr)
777 _M_pi->_M_weak_release();
778 }
779
780 __weak_count&
781 operator=(const __shared_count<_Lp>& __r) noexcept
782 {
783 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
784 if (__tmp != nullptr)
785 __tmp->_M_weak_add_ref();
786 if (_M_pi != nullptr)
787 _M_pi->_M_weak_release();
788 _M_pi = __tmp;
789 return *this;
790 }
791
792 __weak_count&
793 operator=(const __weak_count& __r) noexcept
794 {
795 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
796 if (__tmp != nullptr)
797 __tmp->_M_weak_add_ref();
798 if (_M_pi != nullptr)
799 _M_pi->_M_weak_release();
800 _M_pi = __tmp;
801 return *this;
802 }
803
804 __weak_count&
805 operator=(__weak_count&& __r) noexcept
806 {
807 if (_M_pi != nullptr)
808 _M_pi->_M_weak_release();
809 _M_pi = __r._M_pi;
810 __r._M_pi = nullptr;
811 return *this;
812 }
813
814 void
815 _M_swap(__weak_count& __r) noexcept
816 {
817 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
818 __r._M_pi = _M_pi;
819 _M_pi = __tmp;
820 }
821
822 long
823 _M_get_use_count() const noexcept
824 { return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; }
825
826 bool
827 _M_less(const __weak_count& __rhs) const noexcept
828 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
829
830 bool
831 _M_less(const __shared_count<_Lp>& __rhs) const noexcept
832 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
833
834 // Friend function injected into enclosing namespace and found by ADL
835 friend inline bool
836 operator==(const __weak_count& __a, const __weak_count& __b) noexcept
837 { return __a._M_pi == __b._M_pi; }
838
839 private:
840 friend class __shared_count<_Lp>;
841
842 _Sp_counted_base<_Lp>* _M_pi;
843 };
844
845 // Now that __weak_count is defined we can define this constructor:
846 template<_Lock_policy _Lp>
847 inline
848 __shared_count<_Lp>::__shared_count(const __weak_count<_Lp>& __r)
849 : _M_pi(__r._M_pi)
850 {
851 if (_M_pi != nullptr)
852 _M_pi->_M_add_ref_lock();
853 else
854 __throw_bad_weak_ptr();
855 }
856
857 // Now that __weak_count is defined we can define this constructor:
858 template<_Lock_policy _Lp>
859 inline
860 __shared_count<_Lp>::
861 __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t)
862 : _M_pi(__r._M_pi)
863 {
864 if (_M_pi != nullptr)
865 if (!_M_pi->_M_add_ref_lock_nothrow())
866 _M_pi = nullptr;
867 }
868
869#define __cpp_lib_shared_ptr_arrays201603 201603
870
871 // Helper traits for shared_ptr of array:
872
873 // A pointer type Y* is said to be compatible with a pointer type T* when
874 // either Y* is convertible to T* or Y is U[N] and T is U cv [].
875 template<typename _Yp_ptr, typename _Tp_ptr>
876 struct __sp_compatible_with
877 : false_type
878 { };
879
880 template<typename _Yp, typename _Tp>
881 struct __sp_compatible_with<_Yp*, _Tp*>
882 : is_convertible<_Yp*, _Tp*>::type
883 { };
884
885 template<typename _Up, size_t _Nm>
886 struct __sp_compatible_with<_Up(*)[_Nm], _Up(*)[]>
887 : true_type
888 { };
889
890 template<typename _Up, size_t _Nm>
891 struct __sp_compatible_with<_Up(*)[_Nm], const _Up(*)[]>
892 : true_type
893 { };
894
895 template<typename _Up, size_t _Nm>
896 struct __sp_compatible_with<_Up(*)[_Nm], volatile _Up(*)[]>
897 : true_type
898 { };
899
900 template<typename _Up, size_t _Nm>
901 struct __sp_compatible_with<_Up(*)[_Nm], const volatile _Up(*)[]>
902 : true_type
903 { };
904
905 // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N].
906 template<typename _Up, size_t _Nm, typename _Yp, typename = void>
907 struct __sp_is_constructible_arrN
908 : false_type
909 { };
910
911 template<typename _Up, size_t _Nm, typename _Yp>
912 struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>>
913 : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type
914 { };
915
916 // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[].
917 template<typename _Up, typename _Yp, typename = void>
918 struct __sp_is_constructible_arr
919 : false_type
920 { };
921
922 template<typename _Up, typename _Yp>
923 struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>>
924 : is_convertible<_Yp(*)[], _Up(*)[]>::type
925 { };
926
927 // Trait to check if shared_ptr<T> can be constructed from Y*.
928 template<typename _Tp, typename _Yp>
929 struct __sp_is_constructible;
930
931 // When T is U[N], Y(*)[N] shall be convertible to T*;
932 template<typename _Up, size_t _Nm, typename _Yp>
933 struct __sp_is_constructible<_Up[_Nm], _Yp>
934 : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type
935 { };
936
937 // when T is U[], Y(*)[] shall be convertible to T*;
938 template<typename _Up, typename _Yp>
939 struct __sp_is_constructible<_Up[], _Yp>
940 : __sp_is_constructible_arr<_Up, _Yp>::type
941 { };
942
943 // otherwise, Y* shall be convertible to T*.
944 template<typename _Tp, typename _Yp>
945 struct __sp_is_constructible
946 : is_convertible<_Yp*, _Tp*>::type
947 { };
948
949
950 // Define operator* and operator-> for shared_ptr<T>.
951 template<typename _Tp, _Lock_policy _Lp,
952 bool = is_array<_Tp>::value, bool = is_void<_Tp>::value>
953 class __shared_ptr_access
954 {
955 public:
956 using element_type = _Tp;
957
958 element_type&
959 operator*() const noexcept
960 {
961 __glibcxx_assert(_M_get() != nullptr);
962 return *_M_get();
963 }
964
965 element_type*
966 operator->() const noexcept
967 {
968 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
969 return _M_get();
970 }
971
972 private:
973 element_type*
974 _M_get() const noexcept
975 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
976 };
977
978 // Define operator-> for shared_ptr<cv void>.
979 template<typename _Tp, _Lock_policy _Lp>
980 class __shared_ptr_access<_Tp, _Lp, false, true>
981 {
982 public:
983 using element_type = _Tp;
984
985 element_type*
986 operator->() const noexcept
987 {
988 auto __ptr = static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get();
989 _GLIBCXX_DEBUG_PEDASSERT(__ptr != nullptr);
990 return __ptr;
991 }
992 };
993
994 // Define operator[] for shared_ptr<T[]> and shared_ptr<T[N]>.
995 template<typename _Tp, _Lock_policy _Lp>
996 class __shared_ptr_access<_Tp, _Lp, true, false>
997 {
998 public:
999 using element_type = typename remove_extent<_Tp>::type;
1000
1001#if __cplusplus201103L <= 201402L
1002 [[__deprecated__("shared_ptr<T[]>::operator* is absent from C++17")]]
1003 element_type&
1004 operator*() const noexcept
1005 {
1006 __glibcxx_assert(_M_get() != nullptr);
1007 return *_M_get();
1008 }
1009
1010 [[__deprecated__("shared_ptr<T[]>::operator-> is absent from C++17")]]
1011 element_type*
1012 operator->() const noexcept
1013 {
1014 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
1015 return _M_get();
1016 }
1017#endif
1018
1019 element_type&
1020 operator[](ptrdiff_t __i) const
1021 {
1022 __glibcxx_assert(_M_get() != nullptr);
1023 __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value);
1024 return _M_get()[__i];
1025 }
1026
1027 private:
1028 element_type*
1029 _M_get() const noexcept
1030 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
1031 };
1032
1033 template<typename _Tp, _Lock_policy _Lp>
1034 class __shared_ptr
1035 : public __shared_ptr_access<_Tp, _Lp>
1036 {
1037 public:
1038 using element_type = typename remove_extent<_Tp>::type;
1039
1040 private:
1041 // Constraint for taking ownership of a pointer of type _Yp*:
1042 template<typename _Yp>
1043 using _SafeConv
1044 = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type;
1045
1046 // Constraint for construction from shared_ptr and weak_ptr:
1047 template<typename _Yp, typename _Res = void>
1048 using _Compatible = typename
1049 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
1050
1051 // Constraint for assignment from shared_ptr and weak_ptr:
1052 template<typename _Yp>
1053 using _Assignable = _Compatible<_Yp, __shared_ptr&>;
1054
1055 // Constraint for construction from unique_ptr:
1056 template<typename _Yp, typename _Del, typename _Res = void,
1057 typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer>
1058 using _UniqCompatible = typename enable_if<__and_<
1059 __sp_compatible_with<_Yp*, _Tp*>, is_convertible<_Ptr, element_type*>
1060 >::value, _Res>::type;
1061
1062 // Constraint for assignment from unique_ptr:
1063 template<typename _Yp, typename _Del>
1064 using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>;
1065
1066 public:
1067
1068#if __cplusplus201103L > 201402L
1069 using weak_type = __weak_ptr<_Tp, _Lp>;
1070#endif
1071
1072 constexpr __shared_ptr() noexcept
1073 : _M_ptr(0), _M_refcount()
1074 { }
1075
1076 template<typename _Yp, typename = _SafeConv<_Yp>>
1077 explicit
1078 __shared_ptr(_Yp* __p)
1079 : _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type())
1080 {
1081 static_assert( !is_void<_Yp>::value, "incomplete type" );
1082 static_assert( sizeof(_Yp) > 0, "incomplete type" );
1083 _M_enable_shared_from_this_with(__p);
1084 }
1085
1086 template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>>
1087 __shared_ptr(_Yp* __p, _Deleter __d)
1088 : _M_ptr(__p), _M_refcount(__p, std::move(__d))
1089 {
1090 static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
1091 "deleter expression d(p) is well-formed");
1092 _M_enable_shared_from_this_with(__p);
1093 }
1094
1095 template<typename _Yp, typename _Deleter, typename _Alloc,
1096 typename = _SafeConv<_Yp>>
1097 __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
1098 : _M_ptr(__p), _M_refcount(__p, std::move(__d), std::move(__a))
1099 {
1100 static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
1101 "deleter expression d(p) is well-formed");
1102 _M_enable_shared_from_this_with(__p);
1103 }
1104
1105 template<typename _Deleter>
1106 __shared_ptr(nullptr_t __p, _Deleter __d)
1107 : _M_ptr(0), _M_refcount(__p, std::move(__d))
1108 { }
1109
1110 template<typename _Deleter, typename _Alloc>
1111 __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
1112 : _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a))
1113 { }
1114
1115 template<typename _Yp>
1116 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,
1117 element_type* __p) noexcept
1118 : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
1119 { }
1120
1121 __shared_ptr(const __shared_ptr&) noexcept = default;
1122 __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
37
Calling copy assignment operator for '__shared_count'
50
Returning; memory was released
65
Calling copy assignment operator for '__shared_count'
1123 ~__shared_ptr() = default;
1124
1125 template<typename _Yp, typename = _Compatible<_Yp>>
1126 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1127 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
1128 { }
1129
1130 __shared_ptr(__shared_ptr&& __r) noexcept
1131 : _M_ptr(__r._M_ptr), _M_refcount()
1132 {
1133 _M_refcount._M_swap(__r._M_refcount);
1134 __r._M_ptr = 0;
1135 }
1136
1137 template<typename _Yp, typename = _Compatible<_Yp>>
1138 __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept
1139 : _M_ptr(__r._M_ptr), _M_refcount()
1140 {
1141 _M_refcount._M_swap(__r._M_refcount);
1142 __r._M_ptr = 0;
1143 }
1144
1145 template<typename _Yp, typename = _Compatible<_Yp>>
1146 explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r)
1147 : _M_refcount(__r._M_refcount) // may throw
1148 {
1149 // It is now safe to copy __r._M_ptr, as
1150 // _M_refcount(__r._M_refcount) did not throw.
1151 _M_ptr = __r._M_ptr;
1152 }
1153
1154 // If an exception is thrown this constructor has no effect.
1155 template<typename _Yp, typename _Del,
1156 typename = _UniqCompatible<_Yp, _Del>>
1157 __shared_ptr(unique_ptr<_Yp, _Del>&& __r)
1158 : _M_ptr(__r.get()), _M_refcount()
1159 {
1160 auto __raw = _S_raw_ptr(__r.get());
1161 _M_refcount = __shared_count<_Lp>(std::move(__r));
1162 _M_enable_shared_from_this_with(__raw);
1163 }
1164
1165#if __cplusplus201103L <= 201402L && _GLIBCXX_USE_DEPRECATED1
1166 protected:
1167 // If an exception is thrown this constructor has no effect.
1168 template<typename _Tp1, typename _Del,
1169 typename enable_if<__and_<
1170 __not_<is_array<_Tp>>, is_array<_Tp1>,
1171 is_convertible<typename unique_ptr<_Tp1, _Del>::pointer, _Tp*>
1172 >::value, bool>::type = true>
1173 __shared_ptr(unique_ptr<_Tp1, _Del>&& __r, __sp_array_delete)
1174 : _M_ptr(__r.get()), _M_refcount()
1175 {
1176 auto __raw = _S_raw_ptr(__r.get());
1177 _M_refcount = __shared_count<_Lp>(std::move(__r));
1178 _M_enable_shared_from_this_with(__raw);
1179 }
1180 public:
1181#endif
1182
1183#if _GLIBCXX_USE_DEPRECATED1
1184 // Postcondition: use_count() == 1 and __r.get() == 0
1185 template<typename _Yp, typename = _Compatible<_Yp>>
1186 __shared_ptr(auto_ptr<_Yp>&& __r);
1187#endif
1188
1189 constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
1190
1191 template<typename _Yp>
1192 _Assignable<_Yp>
1193 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1194 {
1195 _M_ptr = __r._M_ptr;
1196 _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
1197 return *this;
1198 }
1199
1200#if _GLIBCXX_USE_DEPRECATED1
1201 template<typename _Yp>
1202 _Assignable<_Yp>
1203 operator=(auto_ptr<_Yp>&& __r)
1204 {
1205 __shared_ptr(std::move(__r)).swap(*this);
1206 return *this;
1207 }
1208#endif
1209
1210 __shared_ptr&
1211 operator=(__shared_ptr&& __r) noexcept
1212 {
1213 __shared_ptr(std::move(__r)).swap(*this);
1214 return *this;
1215 }
1216
1217 template<class _Yp>
1218 _Assignable<_Yp>
1219 operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept
1220 {
1221 __shared_ptr(std::move(__r)).swap(*this);
1222 return *this;
1223 }
1224
1225 template<typename _Yp, typename _Del>
1226 _UniqAssignable<_Yp, _Del>
1227 operator=(unique_ptr<_Yp, _Del>&& __r)
1228 {
1229 __shared_ptr(std::move(__r)).swap(*this);
1230 return *this;
1231 }
1232
1233 void
1234 reset() noexcept
1235 { __shared_ptr().swap(*this); }
1236
1237 template<typename _Yp>
1238 _SafeConv<_Yp>
1239 reset(_Yp* __p) // _Yp must be complete.
1240 {
1241 // Catch self-reset errors.
1242 __glibcxx_assert(__p == 0 || __p != _M_ptr);
1243 __shared_ptr(__p).swap(*this);
1244 }
1245
1246 template<typename _Yp, typename _Deleter>
1247 _SafeConv<_Yp>
1248 reset(_Yp* __p, _Deleter __d)
1249 { __shared_ptr(__p, std::move(__d)).swap(*this); }
1250
1251 template<typename _Yp, typename _Deleter, typename _Alloc>
1252 _SafeConv<_Yp>
1253 reset(_Yp* __p, _Deleter __d, _Alloc __a)
1254 { __shared_ptr(__p, std::move(__d), std::move(__a)).swap(*this); }
1255
1256 element_type*
1257 get() const noexcept
1258 { return _M_ptr; }
1259
1260 explicit operator bool() const // never throws
1261 { return _M_ptr == 0 ? false : true; }
1262
1263 bool
1264 unique() const noexcept
1265 { return _M_refcount._M_unique(); }
1266
1267 long
1268 use_count() const noexcept
1269 { return _M_refcount._M_get_use_count(); }
1270
1271 void
1272 swap(__shared_ptr<_Tp, _Lp>& __other) noexcept
1273 {
1274 std::swap(_M_ptr, __other._M_ptr);
1275 _M_refcount._M_swap(__other._M_refcount);
1276 }
1277
1278 template<typename _Tp1>
1279 bool
1280 owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept
1281 { return _M_refcount._M_less(__rhs._M_refcount); }
1282
1283 template<typename _Tp1>
1284 bool
1285 owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept
1286 { return _M_refcount._M_less(__rhs._M_refcount); }
1287
1288#if __cpp_rtti199711
1289 protected:
1290 // This constructor is non-standard, it is used by allocate_shared.
1291 template<typename _Alloc, typename... _Args>
1292 __shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
1293 _Args&&... __args)
1294 : _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
1295 std::forward<_Args>(__args)...)
1296 {
1297 // _M_ptr needs to point to the newly constructed object.
1298 // This relies on _Sp_counted_ptr_inplace::_M_get_deleter.
1299 void* __p = _M_refcount._M_get_deleter(typeid(__tag));
1300 _M_ptr = static_cast<_Tp*>(__p);
1301 _M_enable_shared_from_this_with(_M_ptr);
1302 }
1303#else
1304 template<typename _Alloc>
1305 struct _Deleter
1306 {
1307 void operator()(typename _Alloc::value_type* __ptr)
1308 {
1309 __allocated_ptr<_Alloc> __guard{ _M_alloc, __ptr };
1310 allocator_traits<_Alloc>::destroy(_M_alloc, __guard.get());
1311 }
1312 _Alloc _M_alloc;
1313 };
1314
1315 template<typename _Alloc, typename... _Args>
1316 __shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
1317 _Args&&... __args)
1318 : _M_ptr(), _M_refcount()
1319 {
1320 typedef typename allocator_traits<_Alloc>::template
1321 rebind_traits<typename std::remove_cv<_Tp>::type> __traits;
1322 _Deleter<typename __traits::allocator_type> __del = { __a };
1323 auto __guard = std::__allocate_guarded(__del._M_alloc);
1324 auto __ptr = __guard.get();
1325 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1326 // 2070. allocate_shared should use allocator_traits<A>::construct
1327 __traits::construct(__del._M_alloc, __ptr,
1328 std::forward<_Args>(__args)...);
1329 __guard = nullptr;
1330 __shared_count<_Lp> __count(__ptr, __del, __del._M_alloc);
1331 _M_refcount._M_swap(__count);
1332 _M_ptr = __ptr;
1333 _M_enable_shared_from_this_with(_M_ptr);
1334 }
1335#endif
1336
1337 template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc,
1338 typename... _Args>
1339 friend __shared_ptr<_Tp1, _Lp1>
1340 __allocate_shared(const _Alloc& __a, _Args&&... __args);
1341
1342 // This constructor is used by __weak_ptr::lock() and
1343 // shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t).
1344 __shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t)
1345 : _M_refcount(__r._M_refcount, std::nothrow)
1346 {
1347 _M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr;
1348 }
1349
1350 friend class __weak_ptr<_Tp, _Lp>;
1351
1352 private:
1353
1354 template<typename _Yp>
1355 using __esft_base_t = decltype(__enable_shared_from_this_base(
1356 std::declval<const __shared_count<_Lp>&>(),
1357 std::declval<_Yp*>()));
1358
1359 // Detect an accessible and unambiguous enable_shared_from_this base.
1360 template<typename _Yp, typename = void>
1361 struct __has_esft_base
1362 : false_type { };
1363
1364 template<typename _Yp>
1365 struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>
1366 : __not_<is_array<_Tp>> { }; // No enable shared_from_this for arrays
1367
1368 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
1369 typename enable_if<__has_esft_base<_Yp2>::value>::type
1370 _M_enable_shared_from_this_with(_Yp* __p) noexcept
1371 {
1372 if (auto __base = __enable_shared_from_this_base(_M_refcount, __p))
1373 __base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount);
1374 }
1375
1376 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
1377 typename enable_if<!__has_esft_base<_Yp2>::value>::type
1378 _M_enable_shared_from_this_with(_Yp*) noexcept
1379 { }
1380
1381 void*
1382 _M_get_deleter(const std::type_info& __ti) const noexcept
1383 { return _M_refcount._M_get_deleter(__ti); }
1384
1385 template<typename _Tp1>
1386 static _Tp1*
1387 _S_raw_ptr(_Tp1* __ptr)
1388 { return __ptr; }
1389
1390 template<typename _Tp1>
1391 static auto
1392 _S_raw_ptr(_Tp1 __ptr) -> decltype(std::__addressof(*__ptr))
1393 { return std::__addressof(*__ptr); }
1394
1395 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1396 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1397
1398 template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
1399 friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
1400
1401 element_type* _M_ptr; // Contained pointer.
1402 __shared_count<_Lp> _M_refcount; // Reference counter.
1403 };
1404
1405
1406 // 20.7.2.2.7 shared_ptr comparisons
1407 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1408 inline bool
1409 operator==(const __shared_ptr<_Tp1, _Lp>& __a,
1410 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1411 { return __a.get() == __b.get(); }
1412
1413 template<typename _Tp, _Lock_policy _Lp>
1414 inline bool
1415 operator==(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1416 { return !__a; }
1417
1418 template<typename _Tp, _Lock_policy _Lp>
1419 inline bool
1420 operator==(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1421 { return !__a; }
1422
1423 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1424 inline bool
1425 operator!=(const __shared_ptr<_Tp1, _Lp>& __a,
1426 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1427 { return __a.get() != __b.get(); }
1428
1429 template<typename _Tp, _Lock_policy _Lp>
1430 inline bool
1431 operator!=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1432 { return (bool)__a; }
1433
1434 template<typename _Tp, _Lock_policy _Lp>
1435 inline bool
1436 operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1437 { return (bool)__a; }
1438
1439 template<typename _Tp, typename _Up, _Lock_policy _Lp>
1440 inline bool
1441 operator<(const __shared_ptr<_Tp, _Lp>& __a,
1442 const __shared_ptr<_Up, _Lp>& __b) noexcept
1443 {
1444 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1445 using _Up_elt = typename __shared_ptr<_Up, _Lp>::element_type;
1446 using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
1447 return less<_Vp>()(__a.get(), __b.get());
1448 }
1449
1450 template<typename _Tp, _Lock_policy _Lp>
1451 inline bool
1452 operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1453 {
1454 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1455 return less<_Tp_elt*>()(__a.get(), nullptr);
1456 }
1457
1458 template<typename _Tp, _Lock_policy _Lp>
1459 inline bool
1460 operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1461 {
1462 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1463 return less<_Tp_elt*>()(nullptr, __a.get());
1464 }
1465
1466 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1467 inline bool
1468 operator<=(const __shared_ptr<_Tp1, _Lp>& __a,
1469 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1470 { return !(__b < __a); }
1471
1472 template<typename _Tp, _Lock_policy _Lp>
1473 inline bool
1474 operator<=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1475 { return !(nullptr < __a); }
1476
1477 template<typename _Tp, _Lock_policy _Lp>
1478 inline bool
1479 operator<=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1480 { return !(__a < nullptr); }
1481
1482 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1483 inline bool
1484 operator>(const __shared_ptr<_Tp1, _Lp>& __a,
1485 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1486 { return (__b < __a); }
1487
1488 template<typename _Tp, _Lock_policy _Lp>
1489 inline bool
1490 operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1491 { return nullptr < __a; }
1492
1493 template<typename _Tp, _Lock_policy _Lp>
1494 inline bool
1495 operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1496 { return __a < nullptr; }
1497
1498 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1499 inline bool
1500 operator>=(const __shared_ptr<_Tp1, _Lp>& __a,
1501 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1502 { return !(__a < __b); }
1503
1504 template<typename _Tp, _Lock_policy _Lp>
1505 inline bool
1506 operator>=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1507 { return !(__a < nullptr); }
1508
1509 template<typename _Tp, _Lock_policy _Lp>
1510 inline bool
1511 operator>=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1512 { return !(nullptr < __a); }
1513
1514 template<typename _Sp>
1515 struct _Sp_less : public binary_function<_Sp, _Sp, bool>
1516 {
1517 bool
1518 operator()(const _Sp& __lhs, const _Sp& __rhs) const noexcept
1519 {
1520 typedef typename _Sp::element_type element_type;
1521 return std::less<element_type*>()(__lhs.get(), __rhs.get());
1522 }
1523 };
1524
1525 template<typename _Tp, _Lock_policy _Lp>
1526 struct less<__shared_ptr<_Tp, _Lp>>
1527 : public _Sp_less<__shared_ptr<_Tp, _Lp>>
1528 { };
1529
1530 // 20.7.2.2.8 shared_ptr specialized algorithms.
1531 template<typename _Tp, _Lock_policy _Lp>
1532 inline void
1533 swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept
1534 { __a.swap(__b); }
1535
1536 // 20.7.2.2.9 shared_ptr casts
1537
1538 // The seemingly equivalent code:
1539 // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))
1540 // will eventually result in undefined behaviour, attempting to
1541 // delete the same object twice.
1542 /// static_pointer_cast
1543 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1544 inline __shared_ptr<_Tp, _Lp>
1545 static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1546 {
1547 using _Sp = __shared_ptr<_Tp, _Lp>;
1548 return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
1549 }
1550
1551 // The seemingly equivalent code:
1552 // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
1553 // will eventually result in undefined behaviour, attempting to
1554 // delete the same object twice.
1555 /// const_pointer_cast
1556 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1557 inline __shared_ptr<_Tp, _Lp>
1558 const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1559 {
1560 using _Sp = __shared_ptr<_Tp, _Lp>;
1561 return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
1562 }
1563
1564 // The seemingly equivalent code:
1565 // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
1566 // will eventually result in undefined behaviour, attempting to
1567 // delete the same object twice.
1568 /// dynamic_pointer_cast
1569 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1570 inline __shared_ptr<_Tp, _Lp>
1571 dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1572 {
1573 using _Sp = __shared_ptr<_Tp, _Lp>;
1574 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
1575 return _Sp(__r, __p);
1576 return _Sp();
1577 }
1578
1579#if __cplusplus201103L > 201402L
1580 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1581 inline __shared_ptr<_Tp, _Lp>
1582 reinterpret_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1583 {
1584 using _Sp = __shared_ptr<_Tp, _Lp>;
1585 return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
1586 }
1587#endif
1588
1589 template<typename _Tp, _Lock_policy _Lp>
1590 class __weak_ptr
1591 {
1592 template<typename _Yp, typename _Res = void>
1593 using _Compatible = typename
1594 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
1595
1596 // Constraint for assignment from shared_ptr and weak_ptr:
1597 template<typename _Yp>
1598 using _Assignable = _Compatible<_Yp, __weak_ptr&>;
1599
1600 public:
1601 using element_type = typename remove_extent<_Tp>::type;
1602
1603 constexpr __weak_ptr() noexcept
1604 : _M_ptr(nullptr), _M_refcount()
1605 { }
1606
1607 __weak_ptr(const __weak_ptr&) noexcept = default;
1608
1609 ~__weak_ptr() = default;
1610
1611 // The "obvious" converting constructor implementation:
1612 //
1613 // template<typename _Tp1>
1614 // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
1615 // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
1616 // { }
1617 //
1618 // has a serious problem.
1619 //
1620 // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
1621 // conversion may require access to *__r._M_ptr (virtual inheritance).
1622 //
1623 // It is not possible to avoid spurious access violations since
1624 // in multithreaded programs __r._M_ptr may be invalidated at any point.
1625 template<typename _Yp, typename = _Compatible<_Yp>>
1626 __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept
1627 : _M_refcount(__r._M_refcount)
1628 { _M_ptr = __r.lock().get(); }
1629
1630 template<typename _Yp, typename = _Compatible<_Yp>>
1631 __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1632 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
1633 { }
1634
1635 __weak_ptr(__weak_ptr&& __r) noexcept
1636 : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
1637 { __r._M_ptr = nullptr; }
1638
1639 template<typename _Yp, typename = _Compatible<_Yp>>
1640 __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept
1641 : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
1642 { __r._M_ptr = nullptr; }
1643
1644 __weak_ptr&
1645 operator=(const __weak_ptr& __r) noexcept = default;
1646
1647 template<typename _Yp>
1648 _Assignable<_Yp>
1649 operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept
1650 {
1651 _M_ptr = __r.lock().get();
1652 _M_refcount = __r._M_refcount;
1653 return *this;
1654 }
1655
1656 template<typename _Yp>
1657 _Assignable<_Yp>
1658 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1659 {
1660 _M_ptr = __r._M_ptr;
1661 _M_refcount = __r._M_refcount;
1662 return *this;
1663 }
1664
1665 __weak_ptr&
1666 operator=(__weak_ptr&& __r) noexcept
1667 {
1668 _M_ptr = __r._M_ptr;
1669 _M_refcount = std::move(__r._M_refcount);
1670 __r._M_ptr = nullptr;
1671 return *this;
1672 }
1673
1674 template<typename _Yp>
1675 _Assignable<_Yp>
1676 operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept
1677 {
1678 _M_ptr = __r.lock().get();
1679 _M_refcount = std::move(__r._M_refcount);
1680 __r._M_ptr = nullptr;
1681 return *this;
1682 }
1683
1684 __shared_ptr<_Tp, _Lp>
1685 lock() const noexcept
1686 { return __shared_ptr<element_type, _Lp>(*this, std::nothrow); }
1687
1688 long
1689 use_count() const noexcept
1690 { return _M_refcount._M_get_use_count(); }
1691
1692 bool
1693 expired() const noexcept
1694 { return _M_refcount._M_get_use_count() == 0; }
1695
1696 template<typename _Tp1>
1697 bool
1698 owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const noexcept
1699 { return _M_refcount._M_less(__rhs._M_refcount); }
1700
1701 template<typename _Tp1>
1702 bool
1703 owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept
1704 { return _M_refcount._M_less(__rhs._M_refcount); }
1705
1706 void
1707 reset() noexcept
1708 { __weak_ptr().swap(*this); }
1709
1710 void
1711 swap(__weak_ptr& __s) noexcept
1712 {
1713 std::swap(_M_ptr, __s._M_ptr);
1714 _M_refcount._M_swap(__s._M_refcount);
1715 }
1716
1717 private:
1718 // Used by __enable_shared_from_this.
1719 void
1720 _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept
1721 {
1722 if (use_count() == 0)
1723 {
1724 _M_ptr = __ptr;
1725 _M_refcount = __refcount;
1726 }
1727 }
1728
1729 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1730 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1731 friend class __enable_shared_from_this<_Tp, _Lp>;
1732 friend class enable_shared_from_this<_Tp>;
1733
1734 element_type* _M_ptr; // Contained pointer.
1735 __weak_count<_Lp> _M_refcount; // Reference counter.
1736 };
1737
1738 // 20.7.2.3.6 weak_ptr specialized algorithms.
1739 template<typename _Tp, _Lock_policy _Lp>
1740 inline void
1741 swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) noexcept
1742 { __a.swap(__b); }
1743
1744 template<typename _Tp, typename _Tp1>
1745 struct _Sp_owner_less : public binary_function<_Tp, _Tp, bool>
1746 {
1747 bool
1748 operator()(const _Tp& __lhs, const _Tp& __rhs) const noexcept
1749 { return __lhs.owner_before(__rhs); }
1750
1751 bool
1752 operator()(const _Tp& __lhs, const _Tp1& __rhs) const noexcept
1753 { return __lhs.owner_before(__rhs); }
1754
1755 bool
1756 operator()(const _Tp1& __lhs, const _Tp& __rhs) const noexcept
1757 { return __lhs.owner_before(__rhs); }
1758 };
1759
1760 template<>
1761 struct _Sp_owner_less<void, void>
1762 {
1763 template<typename _Tp, typename _Up>
1764 auto
1765 operator()(const _Tp& __lhs, const _Up& __rhs) const noexcept
1766 -> decltype(__lhs.owner_before(__rhs))
1767 { return __lhs.owner_before(__rhs); }
1768
1769 using is_transparent = void;
1770 };
1771
1772 template<typename _Tp, _Lock_policy _Lp>
1773 struct owner_less<__shared_ptr<_Tp, _Lp>>
1774 : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>>
1775 { };
1776
1777 template<typename _Tp, _Lock_policy _Lp>
1778 struct owner_less<__weak_ptr<_Tp, _Lp>>
1779 : public _Sp_owner_less<__weak_ptr<_Tp, _Lp>, __shared_ptr<_Tp, _Lp>>
1780 { };
1781
1782
1783 template<typename _Tp, _Lock_policy _Lp>
1784 class __enable_shared_from_this
1785 {
1786 protected:
1787 constexpr __enable_shared_from_this() noexcept { }
1788
1789 __enable_shared_from_this(const __enable_shared_from_this&) noexcept { }
1790
1791 __enable_shared_from_this&
1792 operator=(const __enable_shared_from_this&) noexcept
1793 { return *this; }
1794
1795 ~__enable_shared_from_this() { }
1796
1797 public:
1798 __shared_ptr<_Tp, _Lp>
1799 shared_from_this()
1800 { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); }
1801
1802 __shared_ptr<const _Tp, _Lp>
1803 shared_from_this() const
1804 { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); }
1805
1806#if __cplusplus201103L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
1807 __weak_ptr<_Tp, _Lp>
1808 weak_from_this() noexcept
1809 { return this->_M_weak_this; }
1810
1811 __weak_ptr<const _Tp, _Lp>
1812 weak_from_this() const noexcept
1813 { return this->_M_weak_this; }
1814#endif
1815
1816 private:
1817 template<typename _Tp1>
1818 void
1819 _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const noexcept
1820 { _M_weak_this._M_assign(__p, __n); }
1821
1822 friend const __enable_shared_from_this*
1823 __enable_shared_from_this_base(const __shared_count<_Lp>&,
1824 const __enable_shared_from_this* __p)
1825 { return __p; }
1826
1827 template<typename, _Lock_policy>
1828 friend class __shared_ptr;
1829
1830 mutable __weak_ptr<_Tp, _Lp> _M_weak_this;
1831 };
1832
1833 template<typename _Tp, _Lock_policy _Lp, typename _Alloc, typename... _Args>
1834 inline __shared_ptr<_Tp, _Lp>
1835 __allocate_shared(const _Alloc& __a, _Args&&... __args)
1836 {
1837 return __shared_ptr<_Tp, _Lp>(_Sp_make_shared_tag(), __a,
1838 std::forward<_Args>(__args)...);
1839 }
1840
1841 template<typename _Tp, _Lock_policy _Lp, typename... _Args>
1842 inline __shared_ptr<_Tp, _Lp>
1843 __make_shared(_Args&&... __args)
1844 {
1845 typedef typename std::remove_const<_Tp>::type _Tp_nc;
1846 return std::__allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(),
1847 std::forward<_Args>(__args)...);
1848 }
1849
1850 /// std::hash specialization for __shared_ptr.
1851 template<typename _Tp, _Lock_policy _Lp>
1852 struct hash<__shared_ptr<_Tp, _Lp>>
1853 : public __hash_base<size_t, __shared_ptr<_Tp, _Lp>>
1854 {
1855 size_t
1856 operator()(const __shared_ptr<_Tp, _Lp>& __s) const noexcept
1857 {
1858 return hash<typename __shared_ptr<_Tp, _Lp>::element_type*>()(
1859 __s.get());
1860 }
1861 };
1862
1863_GLIBCXX_END_NAMESPACE_VERSION
1864} // namespace
1865
1866#endif // _SHARED_PTR_BASE_H

/usr/lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/ext/atomicity.h

1// Support for atomic operations -*- C++ -*-
2
3// Copyright (C) 2004-2017 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file ext/atomicity.h
26 * This file is a GNU extension to the Standard C++ Library.
27 */
28
29#ifndef _GLIBCXX_ATOMICITY_H1
30#define _GLIBCXX_ATOMICITY_H1 1
31
32#pragma GCC system_header
33
34#include <bits/c++config.h>
35#include <bits/gthr.h>
36#include <bits/atomic_word.h>
37
38namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
39{
40_GLIBCXX_BEGIN_NAMESPACE_VERSION
41
42 // Functions for portable atomic access.
43 // To abstract locking primitives across all thread policies, use:
44 // __exchange_and_add_dispatch
45 // __atomic_add_dispatch
46#ifdef _GLIBCXX_ATOMIC_BUILTINS1
47 static inline _Atomic_word
48 __exchange_and_add(volatile _Atomic_word* __mem, int __val)
49 { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL4); }
50
51 static inline void
52 __atomic_add(volatile _Atomic_word* __mem, int __val)
53 { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL4); }
54#else
55 _Atomic_word
56 __attribute__ ((__unused__))
57 __exchange_and_add(volatile _Atomic_word*, int) throw ();
58
59 void
60 __attribute__ ((__unused__))
61 __atomic_add(volatile _Atomic_word*, int) throw ();
62#endif
63
64 static inline _Atomic_word
65 __exchange_and_add_single(_Atomic_word* __mem, int __val)
66 {
67 _Atomic_word __result = *__mem;
74
Use of memory after it is freed
68 *__mem += __val;
69 return __result;
70 }
71
72 static inline void
73 __atomic_add_single(_Atomic_word* __mem, int __val)
74 { *__mem += __val; }
75
76 static inline _Atomic_word
77 __attribute__ ((__unused__))
78 __exchange_and_add_dispatch(_Atomic_word* __mem, int __val)
79 {
80#ifdef __GTHREADS1
81 if (__gthread_active_p())
71
Assuming the condition is false
72
Taking false branch
82 return __exchange_and_add(__mem, __val);
83 else
84 return __exchange_and_add_single(__mem, __val);
73
Calling '__exchange_and_add_single'
85#else
86 return __exchange_and_add_single(__mem, __val);
87#endif
88 }
89
90 static inline void
91 __attribute__ ((__unused__))
92 __atomic_add_dispatch(_Atomic_word* __mem, int __val)
93 {
94#ifdef __GTHREADS1
95 if (__gthread_active_p())
96 __atomic_add(__mem, __val);
97 else
98 __atomic_add_single(__mem, __val);
99#else
100 __atomic_add_single(__mem, __val);
101#endif
102 }
103
104_GLIBCXX_END_NAMESPACE_VERSION
105} // namespace
106
107// Even if the CPU doesn't need a memory barrier, we need to ensure
108// that the compiler doesn't reorder memory accesses across the
109// barriers.
110#ifndef _GLIBCXX_READ_MEM_BARRIER__atomic_thread_fence (2)
111#define _GLIBCXX_READ_MEM_BARRIER__atomic_thread_fence (2) __atomic_thread_fence (__ATOMIC_ACQUIRE2)
112#endif
113#ifndef _GLIBCXX_WRITE_MEM_BARRIER__atomic_thread_fence (3)
114#define _GLIBCXX_WRITE_MEM_BARRIER__atomic_thread_fence (3) __atomic_thread_fence (__ATOMIC_RELEASE3)
115#endif
116
117#endif