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

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name SymbolFileDWARF.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D HAVE_ROUND -D LLDB_CONFIGURATION_RELEASE -D LLDB_USE_BUILTIN_DEMANGLER -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn326246/build-llvm/tools/lldb/source/Plugins/SymbolFile/DWARF -I /build/llvm-toolchain-snapshot-7~svn326246/tools/lldb/source/Plugins/SymbolFile/DWARF -I /build/llvm-toolchain-snapshot-7~svn326246/build-llvm/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn326246/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn326246/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn326246/include -I /usr/include/python2.7 -I /build/llvm-toolchain-snapshot-7~svn326246/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn326246/build-llvm/tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-7~svn326246/tools/lldb/source/. -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-deprecated-register -Wno-vla-extension -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn326246/build-llvm/tools/lldb/source/Plugins/SymbolFile/DWARF -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-02-28-041547-14988-1 -x c++ /build/llvm-toolchain-snapshot-7~svn326246/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

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

/usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.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.3.0/../../../../include/c++/7.3.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.3.0/../../../../include/c++/7.3.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