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

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

/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