Bug Summary

File:tools/lldb/source/Commands/CommandObjectTarget.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 CommandObjectTarget.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/Commands -I /build/llvm-toolchain-snapshot-7~svn326246/tools/lldb/source/Commands -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/Commands -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/Commands/CommandObjectTarget.cpp

/build/llvm-toolchain-snapshot-7~svn326246/tools/lldb/source/Commands/CommandObjectTarget.cpp

1//===-- CommandObjectTarget.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 "CommandObjectTarget.h"
11
12// Project includes
13#include "lldb/Core/Debugger.h"
14#include "lldb/Core/IOHandler.h"
15#include "lldb/Core/Module.h"
16#include "lldb/Core/ModuleSpec.h"
17#include "lldb/Core/Section.h"
18#include "lldb/Core/State.h"
19#include "lldb/Core/ValueObjectVariable.h"
20#include "lldb/DataFormatters/ValueObjectPrinter.h"
21#include "lldb/Host/OptionParser.h"
22#include "lldb/Host/StringConvert.h"
23#include "lldb/Host/Symbols.h"
24#include "lldb/Interpreter/Args.h"
25#include "lldb/Interpreter/CommandInterpreter.h"
26#include "lldb/Interpreter/CommandReturnObject.h"
27#include "lldb/Interpreter/OptionGroupArchitecture.h"
28#include "lldb/Interpreter/OptionGroupBoolean.h"
29#include "lldb/Interpreter/OptionGroupFile.h"
30#include "lldb/Interpreter/OptionGroupFormat.h"
31#include "lldb/Interpreter/OptionGroupPlatform.h"
32#include "lldb/Interpreter/OptionGroupString.h"
33#include "lldb/Interpreter/OptionGroupUInt64.h"
34#include "lldb/Interpreter/OptionGroupUUID.h"
35#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
36#include "lldb/Interpreter/OptionGroupVariable.h"
37#include "lldb/Interpreter/Options.h"
38#include "lldb/Symbol/CompileUnit.h"
39#include "lldb/Symbol/FuncUnwinders.h"
40#include "lldb/Symbol/LineTable.h"
41#include "lldb/Symbol/ObjectFile.h"
42#include "lldb/Symbol/SymbolFile.h"
43#include "lldb/Symbol/SymbolVendor.h"
44#include "lldb/Symbol/UnwindPlan.h"
45#include "lldb/Symbol/VariableList.h"
46#include "lldb/Target/ABI.h"
47#include "lldb/Target/Process.h"
48#include "lldb/Target/SectionLoadList.h"
49#include "lldb/Target/StackFrame.h"
50#include "lldb/Target/Thread.h"
51#include "lldb/Target/ThreadSpec.h"
52#include "lldb/Utility/Timer.h"
53
54#include "llvm/Support/FileSystem.h"
55#include "llvm/Support/FormatAdapters.h"
56
57// C Includes
58// C++ Includes
59#include <cerrno>
60
61using namespace lldb;
62using namespace lldb_private;
63
64static void DumpTargetInfo(uint32_t target_idx, Target *target,
65 const char *prefix_cstr,
66 bool show_stopped_process_status, Stream &strm) {
67 const ArchSpec &target_arch = target->GetArchitecture();
68
69 Module *exe_module = target->GetExecutableModulePointer();
70 char exe_path[PATH_MAX4096];
71 bool exe_valid = false;
72 if (exe_module)
73 exe_valid = exe_module->GetFileSpec().GetPath(exe_path, sizeof(exe_path));
74
75 if (!exe_valid)
76 ::strcpy(exe_path, "<none>");
77
78 strm.Printf("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx,
79 exe_path);
80
81 uint32_t properties = 0;
82 if (target_arch.IsValid()) {
83 strm.Printf("%sarch=", properties++ > 0 ? ", " : " ( ");
84 target_arch.DumpTriple(strm);
85 properties++;
86 }
87 PlatformSP platform_sp(target->GetPlatform());
88 if (platform_sp)
89 strm.Printf("%splatform=%s", properties++ > 0 ? ", " : " ( ",
90 platform_sp->GetName().GetCString());
91
92 ProcessSP process_sp(target->GetProcessSP());
93 bool show_process_status = false;
94 if (process_sp) {
95 lldb::pid_t pid = process_sp->GetID();
96 StateType state = process_sp->GetState();
97 if (show_stopped_process_status)
98 show_process_status = StateIsStoppedState(state, true);
99 const char *state_cstr = StateAsCString(state);
100 if (pid != LLDB_INVALID_PROCESS_ID0)
101 strm.Printf("%spid=%" PRIu64"l" "u", properties++ > 0 ? ", " : " ( ", pid);
102 strm.Printf("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr);
103 }
104 if (properties > 0)
105 strm.PutCString(" )\n");
106 else
107 strm.EOL();
108 if (show_process_status) {
109 const bool only_threads_with_stop_reason = true;
110 const uint32_t start_frame = 0;
111 const uint32_t num_frames = 1;
112 const uint32_t num_frames_with_source = 1;
113 const bool stop_format = false;
114 process_sp->GetStatus(strm);
115 process_sp->GetThreadStatus(strm, only_threads_with_stop_reason,
116 start_frame, num_frames,
117 num_frames_with_source, stop_format);
118 }
119}
120
121static uint32_t DumpTargetList(TargetList &target_list,
122 bool show_stopped_process_status, Stream &strm) {
123 const uint32_t num_targets = target_list.GetNumTargets();
124 if (num_targets) {
125 TargetSP selected_target_sp(target_list.GetSelectedTarget());
126 strm.PutCString("Current targets:\n");
127 for (uint32_t i = 0; i < num_targets; ++i) {
128 TargetSP target_sp(target_list.GetTargetAtIndex(i));
129 if (target_sp) {
130 bool is_selected = target_sp.get() == selected_target_sp.get();
131 DumpTargetInfo(i, target_sp.get(), is_selected ? "* " : " ",
132 show_stopped_process_status, strm);
133 }
134 }
135 }
136 return num_targets;
137}
138
139#pragma mark CommandObjectTargetCreate
140
141//-------------------------------------------------------------------------
142// "target create"
143//-------------------------------------------------------------------------
144
145class CommandObjectTargetCreate : public CommandObjectParsed {
146public:
147 CommandObjectTargetCreate(CommandInterpreter &interpreter)
148 : CommandObjectParsed(
149 interpreter, "target create",
150 "Create a target using the argument as the main executable.",
151 nullptr),
152 m_option_group(), m_arch_option(),
153 m_core_file(LLDB_OPT_SET_1(1U << 0), false, "core", 'c', 0, eArgTypeFilename,
154 "Fullpath to a core file to use for this target."),
155 m_platform_path(LLDB_OPT_SET_1(1U << 0), false, "platform-path", 'P', 0,
156 eArgTypePath,
157 "Path to the remote file to use for this target."),
158 m_symbol_file(LLDB_OPT_SET_1(1U << 0), false, "symfile", 's', 0,
159 eArgTypeFilename, "Fullpath to a stand alone debug "
160 "symbols file for when debug symbols "
161 "are not in the executable."),
162 m_remote_file(
163 LLDB_OPT_SET_1(1U << 0), false, "remote-file", 'r', 0, eArgTypeFilename,
164 "Fullpath to the file on the remote host if debugging remotely."),
165 m_add_dependents(LLDB_OPT_SET_1(1U << 0), false, "no-dependents", 'd',
166 "Don't load dependent files when creating the target, "
167 "just add the specified executable.",
168 true, true) {
169 CommandArgumentEntry arg;
170 CommandArgumentData file_arg;
171
172 // Define the first (and only) variant of this arg.
173 file_arg.arg_type = eArgTypeFilename;
174 file_arg.arg_repetition = eArgRepeatPlain;
175
176 // There is only one variant this argument could be; put it into the
177 // argument entry.
178 arg.push_back(file_arg);
179
180 // Push the data for the first argument into the m_arguments vector.
181 m_arguments.push_back(arg);
182
183 m_option_group.Append(&m_arch_option, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
184 m_option_group.Append(&m_core_file, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
185 m_option_group.Append(&m_platform_path, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
186 m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
187 m_option_group.Append(&m_remote_file, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
188 m_option_group.Append(&m_add_dependents, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
189 m_option_group.Finalize();
190 }
191
192 ~CommandObjectTargetCreate() override = default;
193
194 Options *GetOptions() override { return &m_option_group; }
195
196 int HandleArgumentCompletion(Args &input, int &cursor_index,
197 int &cursor_char_position,
198 OptionElementVector &opt_element_vector,
199 int match_start_point, int max_return_elements,
200 bool &word_complete,
201 StringList &matches) override {
202 std::string completion_str(input.GetArgumentAtIndex(cursor_index));
203 completion_str.erase(cursor_char_position);
204
205 CommandCompletions::InvokeCommonCompletionCallbacks(
206 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
207 completion_str.c_str(), match_start_point, max_return_elements, nullptr,
208 word_complete, matches);
209 return matches.GetSize();
210 }
211
212protected:
213 bool DoExecute(Args &command, CommandReturnObject &result) override {
214 const size_t argc = command.GetArgumentCount();
215 FileSpec core_file(m_core_file.GetOptionValue().GetCurrentValue());
216 FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue());
217
218 if (core_file) {
219 if (!core_file.Exists()) {
220 result.AppendErrorWithFormat("core file '%s' doesn't exist",
221 core_file.GetPath().c_str());
222 result.SetStatus(eReturnStatusFailed);
223 return false;
224 }
225 if (!core_file.Readable()) {
226 result.AppendErrorWithFormat("core file '%s' is not readable",
227 core_file.GetPath().c_str());
228 result.SetStatus(eReturnStatusFailed);
229 return false;
230 }
231 }
232
233 if (argc == 1 || core_file || remote_file) {
234 FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue());
235 if (symfile) {
236 if (symfile.Exists()) {
237 if (!symfile.Readable()) {
238 result.AppendErrorWithFormat("symbol file '%s' is not readable",
239 symfile.GetPath().c_str());
240 result.SetStatus(eReturnStatusFailed);
241 return false;
242 }
243 } else {
244 char symfile_path[PATH_MAX4096];
245 symfile.GetPath(symfile_path, sizeof(symfile_path));
246 result.AppendErrorWithFormat("invalid symbol file path '%s'",
247 symfile_path);
248 result.SetStatus(eReturnStatusFailed);
249 return false;
250 }
251 }
252
253 const char *file_path = command.GetArgumentAtIndex(0);
254 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION__PRETTY_FUNCTION__);
255 Timer scoped_timer(func_cat, "(lldb) target create '%s'", file_path);
256 FileSpec file_spec;
257
258 if (file_path)
259 file_spec.SetFile(file_path, true);
260
261 bool must_set_platform_path = false;
262
263 Debugger &debugger = m_interpreter.GetDebugger();
264
265 TargetSP target_sp;
266 llvm::StringRef arch_cstr = m_arch_option.GetArchitectureName();
267 const bool get_dependent_files =
268 m_add_dependents.GetOptionValue().GetCurrentValue();
269 Status error(debugger.GetTargetList().CreateTarget(
270 debugger, file_path, arch_cstr, get_dependent_files, nullptr,
271 target_sp));
272
273 if (target_sp) {
274 // Only get the platform after we create the target because we might
275 // have
276 // switched platforms depending on what the arguments were to
277 // CreateTarget()
278 // we can't rely on the selected platform.
279
280 PlatformSP platform_sp = target_sp->GetPlatform();
281
282 if (remote_file) {
283 if (platform_sp) {
284 // I have a remote file.. two possible cases
285 if (file_spec && file_spec.Exists()) {
286 // if the remote file does not exist, push it there
287 if (!platform_sp->GetFileExists(remote_file)) {
288 Status err = platform_sp->PutFile(file_spec, remote_file);
289 if (err.Fail()) {
290 result.AppendError(err.AsCString());
291 result.SetStatus(eReturnStatusFailed);
292 return false;
293 }
294 }
295 } else {
296 // there is no local file and we need one
297 // in order to make the remote ---> local transfer we need a
298 // platform
299 // TODO: if the user has passed in a --platform argument, use it
300 // to fetch the right platform
301 if (!platform_sp) {
302 result.AppendError(
303 "unable to perform remote debugging without a platform");
304 result.SetStatus(eReturnStatusFailed);
305 return false;
306 }
307 if (file_path) {
308 // copy the remote file to the local file
309 Status err = platform_sp->GetFile(remote_file, file_spec);
310 if (err.Fail()) {
311 result.AppendError(err.AsCString());
312 result.SetStatus(eReturnStatusFailed);
313 return false;
314 }
315 } else {
316 // make up a local file
317 result.AppendError("remote --> local transfer without local "
318 "path is not implemented yet");
319 result.SetStatus(eReturnStatusFailed);
320 return false;
321 }
322 }
323 } else {
324 result.AppendError("no platform found for target");
325 result.SetStatus(eReturnStatusFailed);
326 return false;
327 }
328 }
329
330 if (symfile || remote_file) {
331 ModuleSP module_sp(target_sp->GetExecutableModule());
332 if (module_sp) {
333 if (symfile)
334 module_sp->SetSymbolFileFileSpec(symfile);
335 if (remote_file) {
336 std::string remote_path = remote_file.GetPath();
337 target_sp->SetArg0(remote_path.c_str());
338 module_sp->SetPlatformFileSpec(remote_file);
339 }
340 }
341 }
342
343 debugger.GetTargetList().SetSelectedTarget(target_sp.get());
344 if (must_set_platform_path) {
345 ModuleSpec main_module_spec(file_spec);
346 ModuleSP module_sp = target_sp->GetSharedModule(main_module_spec);
347 if (module_sp)
348 module_sp->SetPlatformFileSpec(remote_file);
349 }
350 if (core_file) {
351 char core_path[PATH_MAX4096];
352 core_file.GetPath(core_path, sizeof(core_path));
353 if (core_file.Exists()) {
354 if (!core_file.Readable()) {
355 result.AppendMessageWithFormat(
356 "Core file '%s' is not readable.\n", core_path);
357 result.SetStatus(eReturnStatusFailed);
358 return false;
359 }
360 FileSpec core_file_dir;
361 core_file_dir.GetDirectory() = core_file.GetDirectory();
362 target_sp->GetExecutableSearchPaths().Append(core_file_dir);
363
364 ProcessSP process_sp(target_sp->CreateProcess(
365 m_interpreter.GetDebugger().GetListener(), llvm::StringRef(),
366 &core_file));
367
368 if (process_sp) {
369 // Seems weird that we Launch a core file, but that is
370 // what we do!
371 error = process_sp->LoadCore();
372
373 if (error.Fail()) {
374 result.AppendError(
375 error.AsCString("can't find plug-in for core file"));
376 result.SetStatus(eReturnStatusFailed);
377 return false;
378 } else {
379 result.AppendMessageWithFormat(
380 "Core file '%s' (%s) was loaded.\n", core_path,
381 target_sp->GetArchitecture().GetArchitectureName());
382 result.SetStatus(eReturnStatusSuccessFinishNoResult);
383 }
384 } else {
385 result.AppendErrorWithFormat(
386 "Unable to find process plug-in for core file '%s'\n",
387 core_path);
388 result.SetStatus(eReturnStatusFailed);
389 }
390 } else {
391 result.AppendErrorWithFormat("Core file '%s' does not exist\n",
392 core_path);
393 result.SetStatus(eReturnStatusFailed);
394 }
395 } else {
396 result.AppendMessageWithFormat(
397 "Current executable set to '%s' (%s).\n", file_path,
398 target_sp->GetArchitecture().GetArchitectureName());
399 result.SetStatus(eReturnStatusSuccessFinishNoResult);
400 }
401 } else {
402 result.AppendError(error.AsCString());
403 result.SetStatus(eReturnStatusFailed);
404 }
405 } else {
406 result.AppendErrorWithFormat("'%s' takes exactly one executable path "
407 "argument, or use the --core option.\n",
408 m_cmd_name.c_str());
409 result.SetStatus(eReturnStatusFailed);
410 }
411 return result.Succeeded();
412 }
413
414private:
415 OptionGroupOptions m_option_group;
416 OptionGroupArchitecture m_arch_option;
417 OptionGroupFile m_core_file;
418 OptionGroupFile m_platform_path;
419 OptionGroupFile m_symbol_file;
420 OptionGroupFile m_remote_file;
421 OptionGroupBoolean m_add_dependents;
422};
423
424#pragma mark CommandObjectTargetList
425
426//----------------------------------------------------------------------
427// "target list"
428//----------------------------------------------------------------------
429
430class CommandObjectTargetList : public CommandObjectParsed {
431public:
432 CommandObjectTargetList(CommandInterpreter &interpreter)
433 : CommandObjectParsed(
434 interpreter, "target list",
435 "List all current targets in the current debug session.", nullptr) {
436 }
437
438 ~CommandObjectTargetList() override = default;
439
440protected:
441 bool DoExecute(Args &args, CommandReturnObject &result) override {
442 if (args.GetArgumentCount() == 0) {
443 Stream &strm = result.GetOutputStream();
444
445 bool show_stopped_process_status = false;
446 if (DumpTargetList(m_interpreter.GetDebugger().GetTargetList(),
447 show_stopped_process_status, strm) == 0) {
448 strm.PutCString("No targets.\n");
449 }
450 result.SetStatus(eReturnStatusSuccessFinishResult);
451 } else {
452 result.AppendError("the 'target list' command takes no arguments\n");
453 result.SetStatus(eReturnStatusFailed);
454 }
455 return result.Succeeded();
456 }
457};
458
459#pragma mark CommandObjectTargetSelect
460
461//----------------------------------------------------------------------
462// "target select"
463//----------------------------------------------------------------------
464
465class CommandObjectTargetSelect : public CommandObjectParsed {
466public:
467 CommandObjectTargetSelect(CommandInterpreter &interpreter)
468 : CommandObjectParsed(
469 interpreter, "target select",
470 "Select a target as the current target by target index.", nullptr) {
471 }
472
473 ~CommandObjectTargetSelect() override = default;
474
475protected:
476 bool DoExecute(Args &args, CommandReturnObject &result) override {
477 if (args.GetArgumentCount() == 1) {
478 bool success = false;
479 const char *target_idx_arg = args.GetArgumentAtIndex(0);
480 uint32_t target_idx =
481 StringConvert::ToUInt32(target_idx_arg, UINT32_MAX(4294967295U), 0, &success);
482 if (success) {
483 TargetList &target_list = m_interpreter.GetDebugger().GetTargetList();
484 const uint32_t num_targets = target_list.GetNumTargets();
485 if (target_idx < num_targets) {
486 TargetSP target_sp(target_list.GetTargetAtIndex(target_idx));
487 if (target_sp) {
488 Stream &strm = result.GetOutputStream();
489 target_list.SetSelectedTarget(target_sp.get());
490 bool show_stopped_process_status = false;
491 DumpTargetList(target_list, show_stopped_process_status, strm);
492 result.SetStatus(eReturnStatusSuccessFinishResult);
493 } else {
494 result.AppendErrorWithFormat("target #%u is NULL in target list\n",
495 target_idx);
496 result.SetStatus(eReturnStatusFailed);
497 }
498 } else {
499 if (num_targets > 0) {
500 result.AppendErrorWithFormat(
501 "index %u is out of range, valid target indexes are 0 - %u\n",
502 target_idx, num_targets - 1);
503 } else {
504 result.AppendErrorWithFormat(
505 "index %u is out of range since there are no active targets\n",
506 target_idx);
507 }
508 result.SetStatus(eReturnStatusFailed);
509 }
510 } else {
511 result.AppendErrorWithFormat("invalid index string value '%s'\n",
512 target_idx_arg);
513 result.SetStatus(eReturnStatusFailed);
514 }
515 } else {
516 result.AppendError(
517 "'target select' takes a single argument: a target index\n");
518 result.SetStatus(eReturnStatusFailed);
519 }
520 return result.Succeeded();
521 }
522};
523
524#pragma mark CommandObjectTargetSelect
525
526//----------------------------------------------------------------------
527// "target delete"
528//----------------------------------------------------------------------
529
530class CommandObjectTargetDelete : public CommandObjectParsed {
531public:
532 CommandObjectTargetDelete(CommandInterpreter &interpreter)
533 : CommandObjectParsed(interpreter, "target delete",
534 "Delete one or more targets by target index.",
535 nullptr),
536 m_option_group(), m_all_option(LLDB_OPT_SET_1(1U << 0), false, "all", 'a',
537 "Delete all targets.", false, true),
538 m_cleanup_option(
539 LLDB_OPT_SET_1(1U << 0), false, "clean", 'c',
540 "Perform extra cleanup to minimize memory consumption after "
541 "deleting the target. "
542 "By default, LLDB will keep in memory any modules previously "
543 "loaded by the target as well "
544 "as all of its debug info. Specifying --clean will unload all of "
545 "these shared modules and "
546 "cause them to be reparsed again the next time the target is run",
547 false, true) {
548 m_option_group.Append(&m_all_option, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
549 m_option_group.Append(&m_cleanup_option, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
550 m_option_group.Finalize();
551 }
552
553 ~CommandObjectTargetDelete() override = default;
554
555 Options *GetOptions() override { return &m_option_group; }
556
557protected:
558 bool DoExecute(Args &args, CommandReturnObject &result) override {
559 const size_t argc = args.GetArgumentCount();
560 std::vector<TargetSP> delete_target_list;
561 TargetList &target_list = m_interpreter.GetDebugger().GetTargetList();
562 TargetSP target_sp;
563
564 if (m_all_option.GetOptionValue()) {
1
Assuming the condition is false
2
Taking false branch
565 for (int i = 0; i < target_list.GetNumTargets(); ++i)
566 delete_target_list.push_back(target_list.GetTargetAtIndex(i));
567 } else if (argc > 0) {
3
Assuming 'argc' is <= 0
4
Taking false branch
568 const uint32_t num_targets = target_list.GetNumTargets();
569 // Bail out if don't have any targets.
570 if (num_targets == 0) {
571 result.AppendError("no targets to delete");
572 result.SetStatus(eReturnStatusFailed);
573 return false;
574 }
575
576 for (auto &entry : args.entries()) {
577 uint32_t target_idx;
578 if (entry.ref.getAsInteger(0, target_idx)) {
579 result.AppendErrorWithFormat("invalid target index '%s'\n",
580 entry.c_str());
581 result.SetStatus(eReturnStatusFailed);
582 return false;
583 }
584 if (target_idx < num_targets) {
585 target_sp = target_list.GetTargetAtIndex(target_idx);
586 if (target_sp) {
587 delete_target_list.push_back(target_sp);
588 continue;
589 }
590 }
591 if (num_targets > 1)
592 result.AppendErrorWithFormat("target index %u is out of range, valid "
593 "target indexes are 0 - %u\n",
594 target_idx, num_targets - 1);
595 else
596 result.AppendErrorWithFormat(
597 "target index %u is out of range, the only valid index is 0\n",
598 target_idx);
599
600 result.SetStatus(eReturnStatusFailed);
601 return false;
602 }
603 } else {
604 target_sp = target_list.GetSelectedTarget();
605 if (!target_sp) {
5
Taking false branch
606 result.AppendErrorWithFormat("no target is currently selected\n");
607 result.SetStatus(eReturnStatusFailed);
608 return false;
609 }
610 delete_target_list.push_back(target_sp);
611 }
612
613 const size_t num_targets_to_delete = delete_target_list.size();
614 for (size_t idx = 0; idx < num_targets_to_delete; ++idx) {
6
Assuming 'idx' is < 'num_targets_to_delete'
7
Loop condition is true. Entering loop body
8
Assuming 'idx' is < 'num_targets_to_delete'
9
Loop condition is true. Entering loop body
10
Assuming 'idx' is < 'num_targets_to_delete'
11
Loop condition is true. Entering loop body
32
Assuming 'idx' is < 'num_targets_to_delete'
33
Loop condition is true. Entering loop body
615 target_sp = delete_target_list[idx];
12
Calling defaulted copy assignment operator for 'shared_ptr'
31
Returning; memory was released
34
Calling defaulted copy assignment operator for 'shared_ptr'
616 target_list.DeleteTarget(target_sp);
617 target_sp->Destroy();
618 }
619 // If "--clean" was specified, prune any orphaned shared modules from
620 // the global shared module list
621 if (m_cleanup_option.GetOptionValue()) {
622 const bool mandatory = true;
623 ModuleList::RemoveOrphanSharedModules(mandatory);
624 }
625 result.GetOutputStream().Printf("%u targets deleted.\n",
626 (uint32_t)num_targets_to_delete);
627 result.SetStatus(eReturnStatusSuccessFinishResult);
628
629 return true;
630 }
631
632 OptionGroupOptions m_option_group;
633 OptionGroupBoolean m_all_option;
634 OptionGroupBoolean m_cleanup_option;
635};
636
637#pragma mark CommandObjectTargetVariable
638
639//----------------------------------------------------------------------
640// "target variable"
641//----------------------------------------------------------------------
642
643class CommandObjectTargetVariable : public CommandObjectParsed {
644 static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file'
645 static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb'
646
647public:
648 CommandObjectTargetVariable(CommandInterpreter &interpreter)
649 : CommandObjectParsed(interpreter, "target variable",
650 "Read global variables for the current target, "
651 "before or while running a process.",
652 nullptr, eCommandRequiresTarget),
653 m_option_group(),
654 m_option_variable(false), // Don't include frame options
655 m_option_format(eFormatDefault),
656 m_option_compile_units(LLDB_OPT_SET_1(1U << 0), false, "file", SHORT_OPTION_FILE,
657 0, eArgTypeFilename,
658 "A basename or fullpath to a file that contains "
659 "global variables. This option can be "
660 "specified multiple times."),
661 m_option_shared_libraries(
662 LLDB_OPT_SET_1(1U << 0), false, "shlib", SHORT_OPTION_SHLB, 0,
663 eArgTypeFilename,
664 "A basename or fullpath to a shared library to use in the search "
665 "for global "
666 "variables. This option can be specified multiple times."),
667 m_varobj_options() {
668 CommandArgumentEntry arg;
669 CommandArgumentData var_name_arg;
670
671 // Define the first (and only) variant of this arg.
672 var_name_arg.arg_type = eArgTypeVarName;
673 var_name_arg.arg_repetition = eArgRepeatPlus;
674
675 // There is only one variant this argument could be; put it into the
676 // argument entry.
677 arg.push_back(var_name_arg);
678
679 // Push the data for the first argument into the m_arguments vector.
680 m_arguments.push_back(arg);
681
682 m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
683 m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
684 m_option_group.Append(&m_option_format,
685 OptionGroupFormat::OPTION_GROUP_FORMAT |
686 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
687 LLDB_OPT_SET_1(1U << 0));
688 m_option_group.Append(&m_option_compile_units, LLDB_OPT_SET_ALL0xFFFFFFFFU,
689 LLDB_OPT_SET_1(1U << 0));
690 m_option_group.Append(&m_option_shared_libraries, LLDB_OPT_SET_ALL0xFFFFFFFFU,
691 LLDB_OPT_SET_1(1U << 0));
692 m_option_group.Finalize();
693 }
694
695 ~CommandObjectTargetVariable() override = default;
696
697 void DumpValueObject(Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp,
698 const char *root_name) {
699 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions());
700
701 if (!valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() &&
702 valobj_sp->IsRuntimeSupportValue())
703 return;
704
705 switch (var_sp->GetScope()) {
706 case eValueTypeVariableGlobal:
707 if (m_option_variable.show_scope)
708 s.PutCString("GLOBAL: ");
709 break;
710
711 case eValueTypeVariableStatic:
712 if (m_option_variable.show_scope)
713 s.PutCString("STATIC: ");
714 break;
715
716 case eValueTypeVariableArgument:
717 if (m_option_variable.show_scope)
718 s.PutCString(" ARG: ");
719 break;
720
721 case eValueTypeVariableLocal:
722 if (m_option_variable.show_scope)
723 s.PutCString(" LOCAL: ");
724 break;
725
726 case eValueTypeVariableThreadLocal:
727 if (m_option_variable.show_scope)
728 s.PutCString("THREAD: ");
729 break;
730
731 default:
732 break;
733 }
734
735 if (m_option_variable.show_decl) {
736 bool show_fullpaths = false;
737 bool show_module = true;
738 if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
739 s.PutCString(": ");
740 }
741
742 const Format format = m_option_format.GetFormat();
743 if (format != eFormatDefault)
744 options.SetFormat(format);
745
746 options.SetRootValueObjectName(root_name);
747
748 valobj_sp->Dump(s, options);
749 }
750
751 static size_t GetVariableCallback(void *baton, const char *name,
752 VariableList &variable_list) {
753 Target *target = static_cast<Target *>(baton);
754 if (target) {
755 return target->GetImages().FindGlobalVariables(ConstString(name), true,
756 UINT32_MAX(4294967295U), variable_list);
757 }
758 return 0;
759 }
760
761 Options *GetOptions() override { return &m_option_group; }
762
763protected:
764 void DumpGlobalVariableList(const ExecutionContext &exe_ctx,
765 const SymbolContext &sc,
766 const VariableList &variable_list, Stream &s) {
767 size_t count = variable_list.GetSize();
768 if (count > 0) {
769 if (sc.module_sp) {
770 if (sc.comp_unit) {
771 s.Printf("Global variables for %s in %s:\n",
772 sc.comp_unit->GetPath().c_str(),
773 sc.module_sp->GetFileSpec().GetPath().c_str());
774 } else {
775 s.Printf("Global variables for %s\n",
776 sc.module_sp->GetFileSpec().GetPath().c_str());
777 }
778 } else if (sc.comp_unit) {
779 s.Printf("Global variables for %s\n", sc.comp_unit->GetPath().c_str());
780 }
781
782 for (uint32_t i = 0; i < count; ++i) {
783 VariableSP var_sp(variable_list.GetVariableAtIndex(i));
784 if (var_sp) {
785 ValueObjectSP valobj_sp(ValueObjectVariable::Create(
786 exe_ctx.GetBestExecutionContextScope(), var_sp));
787
788 if (valobj_sp)
789 DumpValueObject(s, var_sp, valobj_sp,
790 var_sp->GetName().GetCString());
791 }
792 }
793 }
794 }
795
796 bool DoExecute(Args &args, CommandReturnObject &result) override {
797 Target *target = m_exe_ctx.GetTargetPtr();
798 const size_t argc = args.GetArgumentCount();
799 Stream &s = result.GetOutputStream();
800
801 if (argc > 0) {
802
803 // TODO: Convert to entry-based iteration. Requires converting
804 // DumpValueObject.
805 for (size_t idx = 0; idx < argc; ++idx) {
806 VariableList variable_list;
807 ValueObjectList valobj_list;
808
809 const char *arg = args.GetArgumentAtIndex(idx);
810 size_t matches = 0;
811 bool use_var_name = false;
812 if (m_option_variable.use_regex) {
813 RegularExpression regex(llvm::StringRef::withNullAsEmpty(arg));
814 if (!regex.IsValid()) {
815 result.GetErrorStream().Printf(
816 "error: invalid regular expression: '%s'\n", arg);
817 result.SetStatus(eReturnStatusFailed);
818 return false;
819 }
820 use_var_name = true;
821 matches = target->GetImages().FindGlobalVariables(
822 regex, true, UINT32_MAX(4294967295U), variable_list);
823 } else {
824 Status error(Variable::GetValuesForVariableExpressionPath(
825 arg, m_exe_ctx.GetBestExecutionContextScope(),
826 GetVariableCallback, target, variable_list, valobj_list));
827 matches = variable_list.GetSize();
828 }
829
830 if (matches == 0) {
831 result.GetErrorStream().Printf(
832 "error: can't find global variable '%s'\n", arg);
833 result.SetStatus(eReturnStatusFailed);
834 return false;
835 } else {
836 for (uint32_t global_idx = 0; global_idx < matches; ++global_idx) {
837 VariableSP var_sp(variable_list.GetVariableAtIndex(global_idx));
838 if (var_sp) {
839 ValueObjectSP valobj_sp(
840 valobj_list.GetValueObjectAtIndex(global_idx));
841 if (!valobj_sp)
842 valobj_sp = ValueObjectVariable::Create(
843 m_exe_ctx.GetBestExecutionContextScope(), var_sp);
844
845 if (valobj_sp)
846 DumpValueObject(s, var_sp, valobj_sp,
847 use_var_name ? var_sp->GetName().GetCString()
848 : arg);
849 }
850 }
851 }
852 }
853 } else {
854 const FileSpecList &compile_units =
855 m_option_compile_units.GetOptionValue().GetCurrentValue();
856 const FileSpecList &shlibs =
857 m_option_shared_libraries.GetOptionValue().GetCurrentValue();
858 SymbolContextList sc_list;
859 const size_t num_compile_units = compile_units.GetSize();
860 const size_t num_shlibs = shlibs.GetSize();
861 if (num_compile_units == 0 && num_shlibs == 0) {
862 bool success = false;
863 StackFrame *frame = m_exe_ctx.GetFramePtr();
864 CompileUnit *comp_unit = nullptr;
865 if (frame) {
866 SymbolContext sc = frame->GetSymbolContext(eSymbolContextCompUnit);
867 if (sc.comp_unit) {
868 const bool can_create = true;
869 VariableListSP comp_unit_varlist_sp(
870 sc.comp_unit->GetVariableList(can_create));
871 if (comp_unit_varlist_sp) {
872 size_t count = comp_unit_varlist_sp->GetSize();
873 if (count > 0) {
874 DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
875 success = true;
876 }
877 }
878 }
879 }
880 if (!success) {
881 if (frame) {
882 if (comp_unit)
883 result.AppendErrorWithFormat(
884 "no global variables in current compile unit: %s\n",
885 comp_unit->GetPath().c_str());
886 else
887 result.AppendErrorWithFormat(
888 "no debug information for frame %u\n",
889 frame->GetFrameIndex());
890 } else
891 result.AppendError("'target variable' takes one or more global "
892 "variable names as arguments\n");
893 result.SetStatus(eReturnStatusFailed);
894 }
895 } else {
896 SymbolContextList sc_list;
897 const bool append = true;
898 // We have one or more compile unit or shlib
899 if (num_shlibs > 0) {
900 for (size_t shlib_idx = 0; shlib_idx < num_shlibs; ++shlib_idx) {
901 const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx));
902 ModuleSpec module_spec(module_file);
903
904 ModuleSP module_sp(
905 target->GetImages().FindFirstModule(module_spec));
906 if (module_sp) {
907 if (num_compile_units > 0) {
908 for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
909 module_sp->FindCompileUnits(
910 compile_units.GetFileSpecAtIndex(cu_idx), append,
911 sc_list);
912 } else {
913 SymbolContext sc;
914 sc.module_sp = module_sp;
915 sc_list.Append(sc);
916 }
917 } else {
918 // Didn't find matching shlib/module in target...
919 result.AppendErrorWithFormat(
920 "target doesn't contain the specified shared library: %s\n",
921 module_file.GetPath().c_str());
922 }
923 }
924 } else {
925 // No shared libraries, we just want to find globals for the compile
926 // units files that were specified
927 for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
928 target->GetImages().FindCompileUnits(
929 compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list);
930 }
931
932 const uint32_t num_scs = sc_list.GetSize();
933 if (num_scs > 0) {
934 SymbolContext sc;
935 for (uint32_t sc_idx = 0; sc_idx < num_scs; ++sc_idx) {
936 if (sc_list.GetContextAtIndex(sc_idx, sc)) {
937 if (sc.comp_unit) {
938 const bool can_create = true;
939 VariableListSP comp_unit_varlist_sp(
940 sc.comp_unit->GetVariableList(can_create));
941 if (comp_unit_varlist_sp)
942 DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp,
943 s);
944 } else if (sc.module_sp) {
945 // Get all global variables for this module
946 lldb_private::RegularExpression all_globals_regex(
947 llvm::StringRef(
948 ".")); // Any global with at least one character
949 VariableList variable_list;
950 sc.module_sp->FindGlobalVariables(all_globals_regex, append,
951 UINT32_MAX(4294967295U), variable_list);
952 DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s);
953 }
954 }
955 }
956 }
957 }
958 }
959
960 if (m_interpreter.TruncationWarningNecessary()) {
961 result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
962 m_cmd_name.c_str());
963 m_interpreter.TruncationWarningGiven();
964 }
965
966 return result.Succeeded();
967 }
968
969 OptionGroupOptions m_option_group;
970 OptionGroupVariable m_option_variable;
971 OptionGroupFormat m_option_format;
972 OptionGroupFileList m_option_compile_units;
973 OptionGroupFileList m_option_shared_libraries;
974 OptionGroupValueObjectDisplay m_varobj_options;
975};
976
977#pragma mark CommandObjectTargetModulesSearchPathsAdd
978
979class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed {
980public:
981 CommandObjectTargetModulesSearchPathsAdd(CommandInterpreter &interpreter)
982 : CommandObjectParsed(interpreter, "target modules search-paths add",
983 "Add new image search paths substitution pairs to "
984 "the current target.",
985 nullptr) {
986 CommandArgumentEntry arg;
987 CommandArgumentData old_prefix_arg;
988 CommandArgumentData new_prefix_arg;
989
990 // Define the first variant of this arg pair.
991 old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
992 old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
993
994 // Define the first variant of this arg pair.
995 new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
996 new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
997
998 // There are two required arguments that must always occur together, i.e. an
999 // argument "pair". Because they
1000 // must always occur together, they are treated as two variants of one
1001 // argument rather than two independent
1002 // arguments. Push them both into the first argument position for
1003 // m_arguments...
1004
1005 arg.push_back(old_prefix_arg);
1006 arg.push_back(new_prefix_arg);
1007
1008 m_arguments.push_back(arg);
1009 }
1010
1011 ~CommandObjectTargetModulesSearchPathsAdd() override = default;
1012
1013protected:
1014 bool DoExecute(Args &command, CommandReturnObject &result) override {
1015 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1016 if (target) {
1017 const size_t argc = command.GetArgumentCount();
1018 if (argc & 1) {
1019 result.AppendError("add requires an even number of arguments\n");
1020 result.SetStatus(eReturnStatusFailed);
1021 } else {
1022 for (size_t i = 0; i < argc; i += 2) {
1023 const char *from = command.GetArgumentAtIndex(i);
1024 const char *to = command.GetArgumentAtIndex(i + 1);
1025
1026 if (from[0] && to[0]) {
1027 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST(1u << 14));
1028 if (log) {
1029 log->Printf("target modules search path adding ImageSearchPath "
1030 "pair: '%s' -> '%s'",
1031 from, to);
1032 }
1033 bool last_pair = ((argc - i) == 2);
1034 target->GetImageSearchPathList().Append(
1035 ConstString(from), ConstString(to),
1036 last_pair); // Notify if this is the last pair
1037 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1038 } else {
1039 if (from[0])
1040 result.AppendError("<path-prefix> can't be empty\n");
1041 else
1042 result.AppendError("<new-path-prefix> can't be empty\n");
1043 result.SetStatus(eReturnStatusFailed);
1044 }
1045 }
1046 }
1047 } else {
1048 result.AppendError("invalid target\n");
1049 result.SetStatus(eReturnStatusFailed);
1050 }
1051 return result.Succeeded();
1052 }
1053};
1054
1055#pragma mark CommandObjectTargetModulesSearchPathsClear
1056
1057class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed {
1058public:
1059 CommandObjectTargetModulesSearchPathsClear(CommandInterpreter &interpreter)
1060 : CommandObjectParsed(interpreter, "target modules search-paths clear",
1061 "Clear all current image search path substitution "
1062 "pairs from the current target.",
1063 "target modules search-paths clear") {}
1064
1065 ~CommandObjectTargetModulesSearchPathsClear() override = default;
1066
1067protected:
1068 bool DoExecute(Args &command, CommandReturnObject &result) override {
1069 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1070 if (target) {
1071 bool notify = true;
1072 target->GetImageSearchPathList().Clear(notify);
1073 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1074 } else {
1075 result.AppendError("invalid target\n");
1076 result.SetStatus(eReturnStatusFailed);
1077 }
1078 return result.Succeeded();
1079 }
1080};
1081
1082#pragma mark CommandObjectTargetModulesSearchPathsInsert
1083
1084class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed {
1085public:
1086 CommandObjectTargetModulesSearchPathsInsert(CommandInterpreter &interpreter)
1087 : CommandObjectParsed(interpreter, "target modules search-paths insert",
1088 "Insert a new image search path substitution pair "
1089 "into the current target at the specified index.",
1090 nullptr) {
1091 CommandArgumentEntry arg1;
1092 CommandArgumentEntry arg2;
1093 CommandArgumentData index_arg;
1094 CommandArgumentData old_prefix_arg;
1095 CommandArgumentData new_prefix_arg;
1096
1097 // Define the first and only variant of this arg.
1098 index_arg.arg_type = eArgTypeIndex;
1099 index_arg.arg_repetition = eArgRepeatPlain;
1100
1101 // Put the one and only variant into the first arg for m_arguments:
1102 arg1.push_back(index_arg);
1103
1104 // Define the first variant of this arg pair.
1105 old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1106 old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1107
1108 // Define the first variant of this arg pair.
1109 new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1110 new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1111
1112 // There are two required arguments that must always occur together, i.e. an
1113 // argument "pair". Because they
1114 // must always occur together, they are treated as two variants of one
1115 // argument rather than two independent
1116 // arguments. Push them both into the same argument position for
1117 // m_arguments...
1118
1119 arg2.push_back(old_prefix_arg);
1120 arg2.push_back(new_prefix_arg);
1121
1122 // Add arguments to m_arguments.
1123 m_arguments.push_back(arg1);
1124 m_arguments.push_back(arg2);
1125 }
1126
1127 ~CommandObjectTargetModulesSearchPathsInsert() override = default;
1128
1129protected:
1130 bool DoExecute(Args &command, CommandReturnObject &result) override {
1131 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1132 if (target) {
1133 size_t argc = command.GetArgumentCount();
1134 // check for at least 3 arguments and an odd number of parameters
1135 if (argc >= 3 && argc & 1) {
1136 bool success = false;
1137
1138 uint32_t insert_idx = StringConvert::ToUInt32(
1139 command.GetArgumentAtIndex(0), UINT32_MAX(4294967295U), 0, &success);
1140
1141 if (!success) {
1142 result.AppendErrorWithFormat(
1143 "<index> parameter is not an integer: '%s'.\n",
1144 command.GetArgumentAtIndex(0));
1145 result.SetStatus(eReturnStatusFailed);
1146 return result.Succeeded();
1147 }
1148
1149 // shift off the index
1150 command.Shift();
1151 argc = command.GetArgumentCount();
1152
1153 for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) {
1154 const char *from = command.GetArgumentAtIndex(i);
1155 const char *to = command.GetArgumentAtIndex(i + 1);
1156
1157 if (from[0] && to[0]) {
1158 bool last_pair = ((argc - i) == 2);
1159 target->GetImageSearchPathList().Insert(
1160 ConstString(from), ConstString(to), insert_idx, last_pair);
1161 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1162 } else {
1163 if (from[0])
1164 result.AppendError("<path-prefix> can't be empty\n");
1165 else
1166 result.AppendError("<new-path-prefix> can't be empty\n");
1167 result.SetStatus(eReturnStatusFailed);
1168 return false;
1169 }
1170 }
1171 } else {
1172 result.AppendError("insert requires at least three arguments\n");
1173 result.SetStatus(eReturnStatusFailed);
1174 return result.Succeeded();
1175 }
1176
1177 } else {
1178 result.AppendError("invalid target\n");
1179 result.SetStatus(eReturnStatusFailed);
1180 }
1181 return result.Succeeded();
1182 }
1183};
1184
1185#pragma mark CommandObjectTargetModulesSearchPathsList
1186
1187class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed {
1188public:
1189 CommandObjectTargetModulesSearchPathsList(CommandInterpreter &interpreter)
1190 : CommandObjectParsed(interpreter, "target modules search-paths list",
1191 "List all current image search path substitution "
1192 "pairs in the current target.",
1193 "target modules search-paths list") {}
1194
1195 ~CommandObjectTargetModulesSearchPathsList() override = default;
1196
1197protected:
1198 bool DoExecute(Args &command, CommandReturnObject &result) override {
1199 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1200 if (target) {
1201 if (command.GetArgumentCount() != 0) {
1202 result.AppendError("list takes no arguments\n");
1203 result.SetStatus(eReturnStatusFailed);
1204 return result.Succeeded();
1205 }
1206
1207 target->GetImageSearchPathList().Dump(&result.GetOutputStream());
1208 result.SetStatus(eReturnStatusSuccessFinishResult);
1209 } else {
1210 result.AppendError("invalid target\n");
1211 result.SetStatus(eReturnStatusFailed);
1212 }
1213 return result.Succeeded();
1214 }
1215};
1216
1217#pragma mark CommandObjectTargetModulesSearchPathsQuery
1218
1219class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed {
1220public:
1221 CommandObjectTargetModulesSearchPathsQuery(CommandInterpreter &interpreter)
1222 : CommandObjectParsed(
1223 interpreter, "target modules search-paths query",
1224 "Transform a path using the first applicable image search path.",
1225 nullptr) {
1226 CommandArgumentEntry arg;
1227 CommandArgumentData path_arg;
1228
1229 // Define the first (and only) variant of this arg.
1230 path_arg.arg_type = eArgTypeDirectoryName;
1231 path_arg.arg_repetition = eArgRepeatPlain;
1232
1233 // There is only one variant this argument could be; put it into the
1234 // argument entry.
1235 arg.push_back(path_arg);
1236
1237 // Push the data for the first argument into the m_arguments vector.
1238 m_arguments.push_back(arg);
1239 }
1240
1241 ~CommandObjectTargetModulesSearchPathsQuery() override = default;
1242
1243protected:
1244 bool DoExecute(Args &command, CommandReturnObject &result) override {
1245 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1246 if (target) {
1247 if (command.GetArgumentCount() != 1) {
1248 result.AppendError("query requires one argument\n");
1249 result.SetStatus(eReturnStatusFailed);
1250 return result.Succeeded();
1251 }
1252
1253 ConstString orig(command.GetArgumentAtIndex(0));
1254 ConstString transformed;
1255 if (target->GetImageSearchPathList().RemapPath(orig, transformed))
1256 result.GetOutputStream().Printf("%s\n", transformed.GetCString());
1257 else
1258 result.GetOutputStream().Printf("%s\n", orig.GetCString());
1259
1260 result.SetStatus(eReturnStatusSuccessFinishResult);
1261 } else {
1262 result.AppendError("invalid target\n");
1263 result.SetStatus(eReturnStatusFailed);
1264 }
1265 return result.Succeeded();
1266 }
1267};
1268
1269//----------------------------------------------------------------------
1270// Static Helper functions
1271//----------------------------------------------------------------------
1272static void DumpModuleArchitecture(Stream &strm, Module *module,
1273 bool full_triple, uint32_t width) {
1274 if (module) {
1275 StreamString arch_strm;
1276
1277 if (full_triple)
1278 module->GetArchitecture().DumpTriple(arch_strm);
1279 else
1280 arch_strm.PutCString(module->GetArchitecture().GetArchitectureName());
1281 std::string arch_str = arch_strm.GetString();
1282
1283 if (width)
1284 strm.Printf("%-*s", width, arch_str.c_str());
1285 else
1286 strm.PutCString(arch_str);
1287 }
1288}
1289
1290static void DumpModuleUUID(Stream &strm, Module *module) {
1291 if (module && module->GetUUID().IsValid())
1292 module->GetUUID().Dump(&strm);
1293 else
1294 strm.PutCString(" ");
1295}
1296
1297static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter,
1298 Stream &strm, Module *module,
1299 const FileSpec &file_spec,
1300 bool load_addresses) {
1301 uint32_t num_matches = 0;
1302 if (module) {
1303 SymbolContextList sc_list;
1304 num_matches = module->ResolveSymbolContextsForFileSpec(
1305 file_spec, 0, false, eSymbolContextCompUnit, sc_list);
1306
1307 for (uint32_t i = 0; i < num_matches; ++i) {
1308 SymbolContext sc;
1309 if (sc_list.GetContextAtIndex(i, sc)) {
1310 if (i > 0)
1311 strm << "\n\n";
1312
1313 strm << "Line table for " << *static_cast<FileSpec *>(sc.comp_unit)
1314 << " in `" << module->GetFileSpec().GetFilename() << "\n";
1315 LineTable *line_table = sc.comp_unit->GetLineTable();
1316 if (line_table)
1317 line_table->GetDescription(
1318 &strm, interpreter.GetExecutionContext().GetTargetPtr(),
1319 lldb::eDescriptionLevelBrief);
1320 else
1321 strm << "No line table";
1322 }
1323 }
1324 }
1325 return num_matches;
1326}
1327
1328static void DumpFullpath(Stream &strm, const FileSpec *file_spec_ptr,
1329 uint32_t width) {
1330 if (file_spec_ptr) {
1331 if (width > 0) {
1332 std::string fullpath = file_spec_ptr->GetPath();
1333 strm.Printf("%-*s", width, fullpath.c_str());
1334 return;
1335 } else {
1336 file_spec_ptr->Dump(&strm);
1337 return;
1338 }
1339 }
1340 // Keep the width spacing correct if things go wrong...
1341 if (width > 0)
1342 strm.Printf("%-*s", width, "");
1343}
1344
1345static void DumpDirectory(Stream &strm, const FileSpec *file_spec_ptr,
1346 uint32_t width) {
1347 if (file_spec_ptr) {
1348 if (width > 0)
1349 strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
1350 else
1351 file_spec_ptr->GetDirectory().Dump(&strm);
1352 return;
1353 }
1354 // Keep the width spacing correct if things go wrong...
1355 if (width > 0)
1356 strm.Printf("%-*s", width, "");
1357}
1358
1359static void DumpBasename(Stream &strm, const FileSpec *file_spec_ptr,
1360 uint32_t width) {
1361 if (file_spec_ptr) {
1362 if (width > 0)
1363 strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
1364 else
1365 file_spec_ptr->GetFilename().Dump(&strm);
1366 return;
1367 }
1368 // Keep the width spacing correct if things go wrong...
1369 if (width > 0)
1370 strm.Printf("%-*s", width, "");
1371}
1372
1373static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) {
1374 size_t num_dumped = 0;
1375 std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
1376 const size_t num_modules = module_list.GetSize();
1377 if (num_modules > 0) {
1378 strm.Printf("Dumping headers for %" PRIu64"l" "u" " module(s).\n",
1379 static_cast<uint64_t>(num_modules));
1380 strm.IndentMore();
1381 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1382 Module *module = module_list.GetModulePointerAtIndexUnlocked(image_idx);
1383 if (module) {
1384 if (num_dumped++ > 0) {
1385 strm.EOL();
1386 strm.EOL();
1387 }
1388 ObjectFile *objfile = module->GetObjectFile();
1389 objfile->Dump(&strm);
1390 }
1391 }
1392 strm.IndentLess();
1393 }
1394 return num_dumped;
1395}
1396
1397static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm,
1398 Module *module, SortOrder sort_order) {
1399 if (module) {
1400 SymbolVendor *sym_vendor = module->GetSymbolVendor();
1401 if (sym_vendor) {
1402 Symtab *symtab = sym_vendor->GetSymtab();
1403 if (symtab)
1404 symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(),
1405 sort_order);
1406 }
1407 }
1408}
1409
1410static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm,
1411 Module *module) {
1412 if (module) {
1413 SectionList *section_list = module->GetSectionList();
1414 if (section_list) {
1415 strm.Printf("Sections for '%s' (%s):\n",
1416 module->GetSpecificationDescription().c_str(),
1417 module->GetArchitecture().GetArchitectureName());
1418 strm.IndentMore();
1419 section_list->Dump(&strm,
1420 interpreter.GetExecutionContext().GetTargetPtr(), true,
1421 UINT32_MAX(4294967295U));
1422 strm.IndentLess();
1423 }
1424 }
1425}
1426
1427static bool DumpModuleSymbolVendor(Stream &strm, Module *module) {
1428 if (module) {
1429 SymbolVendor *symbol_vendor = module->GetSymbolVendor(true);
1430 if (symbol_vendor) {
1431 symbol_vendor->Dump(&strm);
1432 return true;
1433 }
1434 }
1435 return false;
1436}
1437
1438static void DumpAddress(ExecutionContextScope *exe_scope,
1439 const Address &so_addr, bool verbose, Stream &strm) {
1440 strm.IndentMore();
1441 strm.Indent(" Address: ");
1442 so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
1443 strm.PutCString(" (");
1444 so_addr.Dump(&strm, exe_scope, Address::DumpStyleSectionNameOffset);
1445 strm.PutCString(")\n");
1446 strm.Indent(" Summary: ");
1447 const uint32_t save_indent = strm.GetIndentLevel();
1448 strm.SetIndentLevel(save_indent + 13);
1449 so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription);
1450 strm.SetIndentLevel(save_indent);
1451 // Print out detailed address information when verbose is enabled
1452 if (verbose) {
1453 strm.EOL();
1454 so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext);
1455 }
1456 strm.IndentLess();
1457}
1458
1459static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm,
1460 Module *module, uint32_t resolve_mask,
1461 lldb::addr_t raw_addr, lldb::addr_t offset,
1462 bool verbose) {
1463 if (module) {
1464 lldb::addr_t addr = raw_addr - offset;
1465 Address so_addr;
1466 SymbolContext sc;
1467 Target *target = interpreter.GetExecutionContext().GetTargetPtr();
1468 if (target && !target->GetSectionLoadList().IsEmpty()) {
1469 if (!target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr))
1470 return false;
1471 else if (so_addr.GetModule().get() != module)
1472 return false;
1473 } else {
1474 if (!module->ResolveFileAddress(addr, so_addr))
1475 return false;
1476 }
1477
1478 ExecutionContextScope *exe_scope =
1479 interpreter.GetExecutionContext().GetBestExecutionContextScope();
1480 DumpAddress(exe_scope, so_addr, verbose, strm);
1481 // strm.IndentMore();
1482 // strm.Indent (" Address: ");
1483 // so_addr.Dump (&strm, exe_scope,
1484 // Address::DumpStyleModuleWithFileAddress);
1485 // strm.PutCString (" (");
1486 // so_addr.Dump (&strm, exe_scope,
1487 // Address::DumpStyleSectionNameOffset);
1488 // strm.PutCString (")\n");
1489 // strm.Indent (" Summary: ");
1490 // const uint32_t save_indent = strm.GetIndentLevel ();
1491 // strm.SetIndentLevel (save_indent + 13);
1492 // so_addr.Dump (&strm, exe_scope,
1493 // Address::DumpStyleResolvedDescription);
1494 // strm.SetIndentLevel (save_indent);
1495 // // Print out detailed address information when verbose is enabled
1496 // if (verbose)
1497 // {
1498 // strm.EOL();
1499 // so_addr.Dump (&strm, exe_scope,
1500 // Address::DumpStyleDetailedSymbolContext);
1501 // }
1502 // strm.IndentLess();
1503 return true;
1504 }
1505
1506 return false;
1507}
1508
1509static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
1510 Stream &strm, Module *module,
1511 const char *name, bool name_is_regex,
1512 bool verbose) {
1513 if (module) {
1514 SymbolContext sc;
1515
1516 SymbolVendor *sym_vendor = module->GetSymbolVendor();
1517 if (sym_vendor) {
1518 Symtab *symtab = sym_vendor->GetSymtab();
1519 if (symtab) {
1520 std::vector<uint32_t> match_indexes;
1521 ConstString symbol_name(name);
1522 uint32_t num_matches = 0;
1523 if (name_is_regex) {
1524 RegularExpression name_regexp(symbol_name.GetStringRef());
1525 num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType(
1526 name_regexp, eSymbolTypeAny, match_indexes);
1527 } else {
1528 num_matches =
1529 symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes);
1530 }
1531
1532 if (num_matches > 0) {
1533 strm.Indent();
1534 strm.Printf("%u symbols match %s'%s' in ", num_matches,
1535 name_is_regex ? "the regular expression " : "", name);
1536 DumpFullpath(strm, &module->GetFileSpec(), 0);
1537 strm.PutCString(":\n");
1538 strm.IndentMore();
1539 for (uint32_t i = 0; i < num_matches; ++i) {
1540 Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
1541 if (symbol && symbol->ValueIsAddress()) {
1542 DumpAddress(interpreter.GetExecutionContext()
1543 .GetBestExecutionContextScope(),
1544 symbol->GetAddressRef(), verbose, strm);
1545 }
1546 }
1547 strm.IndentLess();
1548 return num_matches;
1549 }
1550 }
1551 }
1552 }
1553 return 0;
1554}
1555
1556static void DumpSymbolContextList(ExecutionContextScope *exe_scope,
1557 Stream &strm, SymbolContextList &sc_list,
1558 bool verbose) {
1559 strm.IndentMore();
1560
1561 const uint32_t num_matches = sc_list.GetSize();
1562
1563 for (uint32_t i = 0; i < num_matches; ++i) {
1564 SymbolContext sc;
1565 if (sc_list.GetContextAtIndex(i, sc)) {
1566 AddressRange range;
1567
1568 sc.GetAddressRange(eSymbolContextEverything, 0, true, range);
1569
1570 DumpAddress(exe_scope, range.GetBaseAddress(), verbose, strm);
1571 }
1572 }
1573 strm.IndentLess();
1574}
1575
1576static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
1577 Stream &strm, Module *module,
1578 const char *name, bool name_is_regex,
1579 bool include_inlines, bool include_symbols,
1580 bool verbose) {
1581 if (module && name && name[0]) {
1582 SymbolContextList sc_list;
1583 const bool append = true;
1584 size_t num_matches = 0;
1585 if (name_is_regex) {
1586 RegularExpression function_name_regex((llvm::StringRef(name)));
1587 num_matches = module->FindFunctions(function_name_regex, include_symbols,
1588 include_inlines, append, sc_list);
1589 } else {
1590 ConstString function_name(name);
1591 num_matches = module->FindFunctions(
1592 function_name, nullptr, eFunctionNameTypeAuto, include_symbols,
1593 include_inlines, append, sc_list);
1594 }
1595
1596 if (num_matches) {
1597 strm.Indent();
1598 strm.Printf("%" PRIu64"l" "u" " match%s found in ", (uint64_t)num_matches,
1599 num_matches > 1 ? "es" : "");
1600 DumpFullpath(strm, &module->GetFileSpec(), 0);
1601 strm.PutCString(":\n");
1602 DumpSymbolContextList(
1603 interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1604 strm, sc_list, verbose);
1605 }
1606 return num_matches;
1607 }
1608 return 0;
1609}
1610
1611static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
1612 Module *module, const char *name_cstr,
1613 bool name_is_regex) {
1614 if (module && name_cstr && name_cstr[0]) {
1615 TypeList type_list;
1616 const uint32_t max_num_matches = UINT32_MAX(4294967295U);
1617 size_t num_matches = 0;
1618 bool name_is_fully_qualified = false;
1619 SymbolContext sc;
1620
1621 ConstString name(name_cstr);
1622 llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
1623 num_matches =
1624 module->FindTypes(sc, name, name_is_fully_qualified, max_num_matches,
1625 searched_symbol_files, type_list);
1626
1627 if (num_matches) {
1628 strm.Indent();
1629 strm.Printf("%" PRIu64"l" "u" " match%s found in ", (uint64_t)num_matches,
1630 num_matches > 1 ? "es" : "");
1631 DumpFullpath(strm, &module->GetFileSpec(), 0);
1632 strm.PutCString(":\n");
1633 for (TypeSP type_sp : type_list.Types()) {
1634 if (type_sp) {
1635 // Resolve the clang type so that any forward references
1636 // to types that haven't yet been parsed will get parsed.
1637 type_sp->GetFullCompilerType();
1638 type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1639 // Print all typedef chains
1640 TypeSP typedef_type_sp(type_sp);
1641 TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1642 while (typedefed_type_sp) {
1643 strm.EOL();
1644 strm.Printf(" typedef '%s': ",
1645 typedef_type_sp->GetName().GetCString());
1646 typedefed_type_sp->GetFullCompilerType();
1647 typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull,
1648 true);
1649 typedef_type_sp = typedefed_type_sp;
1650 typedefed_type_sp = typedef_type_sp->GetTypedefType();
1651 }
1652 }
1653 strm.EOL();
1654 }
1655 }
1656 return num_matches;
1657 }
1658 return 0;
1659}
1660
1661static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
1662 const SymbolContext &sym_ctx,
1663 const char *name_cstr, bool name_is_regex) {
1664 if (!sym_ctx.module_sp)
1665 return 0;
1666
1667 TypeList type_list;
1668 const uint32_t max_num_matches = UINT32_MAX(4294967295U);
1669 size_t num_matches = 1;
1670 bool name_is_fully_qualified = false;
1671
1672 ConstString name(name_cstr);
1673 llvm::DenseSet<SymbolFile *> searched_symbol_files;
1674 num_matches = sym_ctx.module_sp->FindTypes(
1675 sym_ctx, name, name_is_fully_qualified, max_num_matches,
1676 searched_symbol_files, type_list);
1677
1678 if (num_matches) {
1679 strm.Indent();
1680 strm.PutCString("Best match found in ");
1681 DumpFullpath(strm, &sym_ctx.module_sp->GetFileSpec(), 0);
1682 strm.PutCString(":\n");
1683
1684 TypeSP type_sp(type_list.GetTypeAtIndex(0));
1685 if (type_sp) {
1686 // Resolve the clang type so that any forward references
1687 // to types that haven't yet been parsed will get parsed.
1688 type_sp->GetFullCompilerType();
1689 type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1690 // Print all typedef chains
1691 TypeSP typedef_type_sp(type_sp);
1692 TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1693 while (typedefed_type_sp) {
1694 strm.EOL();
1695 strm.Printf(" typedef '%s': ",
1696 typedef_type_sp->GetName().GetCString());
1697 typedefed_type_sp->GetFullCompilerType();
1698 typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1699 typedef_type_sp = typedefed_type_sp;
1700 typedefed_type_sp = typedef_type_sp->GetTypedefType();
1701 }
1702 }
1703 strm.EOL();
1704 }
1705 return num_matches;
1706}
1707
1708static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
1709 Stream &strm, Module *module,
1710 const FileSpec &file_spec,
1711 uint32_t line, bool check_inlines,
1712 bool verbose) {
1713 if (module && file_spec) {
1714 SymbolContextList sc_list;
1715 const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(
1716 file_spec, line, check_inlines, eSymbolContextEverything, sc_list);
1717 if (num_matches > 0) {
1718 strm.Indent();
1719 strm.Printf("%u match%s found in ", num_matches,
1720 num_matches > 1 ? "es" : "");
1721 strm << file_spec;
1722 if (line > 0)
1723 strm.Printf(":%u", line);
1724 strm << " in ";
1725 DumpFullpath(strm, &module->GetFileSpec(), 0);
1726 strm.PutCString(":\n");
1727 DumpSymbolContextList(
1728 interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1729 strm, sc_list, verbose);
1730 return num_matches;
1731 }
1732 }
1733 return 0;
1734}
1735
1736static size_t FindModulesByName(Target *target, const char *module_name,
1737 ModuleList &module_list,
1738 bool check_global_list) {
1739 FileSpec module_file_spec(module_name, false);
1740 ModuleSpec module_spec(module_file_spec);
1741
1742 const size_t initial_size = module_list.GetSize();
1743
1744 if (check_global_list) {
1745 // Check the global list
1746 std::lock_guard<std::recursive_mutex> guard(
1747 Module::GetAllocationModuleCollectionMutex());
1748 const size_t num_modules = Module::GetNumberAllocatedModules();
1749 ModuleSP module_sp;
1750 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1751 Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
1752
1753 if (module) {
1754 if (module->MatchesModuleSpec(module_spec)) {
1755 module_sp = module->shared_from_this();
1756 module_list.AppendIfNeeded(module_sp);
1757 }
1758 }
1759 }
1760 } else {
1761 if (target) {
1762 const size_t num_matches =
1763 target->GetImages().FindModules(module_spec, module_list);
1764
1765 // Not found in our module list for our target, check the main
1766 // shared module list in case it is a extra file used somewhere
1767 // else
1768 if (num_matches == 0) {
1769 module_spec.GetArchitecture() = target->GetArchitecture();
1770 ModuleList::FindSharedModules(module_spec, module_list);
1771 }
1772 } else {
1773 ModuleList::FindSharedModules(module_spec, module_list);
1774 }
1775 }
1776
1777 return module_list.GetSize() - initial_size;
1778}
1779
1780#pragma mark CommandObjectTargetModulesModuleAutoComplete
1781
1782//----------------------------------------------------------------------
1783// A base command object class that can auto complete with module file
1784// paths
1785//----------------------------------------------------------------------
1786
1787class CommandObjectTargetModulesModuleAutoComplete
1788 : public CommandObjectParsed {
1789public:
1790 CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter,
1791 const char *name,
1792 const char *help,
1793 const char *syntax)
1794 : CommandObjectParsed(interpreter, name, help, syntax) {
1795 CommandArgumentEntry arg;
1796 CommandArgumentData file_arg;
1797
1798 // Define the first (and only) variant of this arg.
1799 file_arg.arg_type = eArgTypeFilename;
1800 file_arg.arg_repetition = eArgRepeatStar;
1801
1802 // There is only one variant this argument could be; put it into the
1803 // argument entry.
1804 arg.push_back(file_arg);
1805
1806 // Push the data for the first argument into the m_arguments vector.
1807 m_arguments.push_back(arg);
1808 }
1809
1810 ~CommandObjectTargetModulesModuleAutoComplete() override = default;
1811
1812 int HandleArgumentCompletion(Args &input, int &cursor_index,
1813 int &cursor_char_position,
1814 OptionElementVector &opt_element_vector,
1815 int match_start_point, int max_return_elements,
1816 bool &word_complete,
1817 StringList &matches) override {
1818 // Arguments are the standard module completer.
1819 std::string completion_str(input.GetArgumentAtIndex(cursor_index));
1820 completion_str.erase(cursor_char_position);
1821
1822 CommandCompletions::InvokeCommonCompletionCallbacks(
1823 GetCommandInterpreter(), CommandCompletions::eModuleCompletion,
1824 completion_str.c_str(), match_start_point, max_return_elements, nullptr,
1825 word_complete, matches);
1826 return matches.GetSize();
1827 }
1828};
1829
1830#pragma mark CommandObjectTargetModulesSourceFileAutoComplete
1831
1832//----------------------------------------------------------------------
1833// A base command object class that can auto complete with module source
1834// file paths
1835//----------------------------------------------------------------------
1836
1837class CommandObjectTargetModulesSourceFileAutoComplete
1838 : public CommandObjectParsed {
1839public:
1840 CommandObjectTargetModulesSourceFileAutoComplete(
1841 CommandInterpreter &interpreter, const char *name, const char *help,
1842 const char *syntax, uint32_t flags)
1843 : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1844 CommandArgumentEntry arg;
1845 CommandArgumentData source_file_arg;
1846
1847 // Define the first (and only) variant of this arg.
1848 source_file_arg.arg_type = eArgTypeSourceFile;
1849 source_file_arg.arg_repetition = eArgRepeatPlus;
1850
1851 // There is only one variant this argument could be; put it into the
1852 // argument entry.
1853 arg.push_back(source_file_arg);
1854
1855 // Push the data for the first argument into the m_arguments vector.
1856 m_arguments.push_back(arg);
1857 }
1858
1859 ~CommandObjectTargetModulesSourceFileAutoComplete() override = default;
1860
1861 int HandleArgumentCompletion(Args &input, int &cursor_index,
1862 int &cursor_char_position,
1863 OptionElementVector &opt_element_vector,
1864 int match_start_point, int max_return_elements,
1865 bool &word_complete,
1866 StringList &matches) override {
1867 // Arguments are the standard source file completer.
1868 std::string completion_str(input.GetArgumentAtIndex(cursor_index));
1869 completion_str.erase(cursor_char_position);
1870
1871 CommandCompletions::InvokeCommonCompletionCallbacks(
1872 GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion,
1873 completion_str.c_str(), match_start_point, max_return_elements, nullptr,
1874 word_complete, matches);
1875 return matches.GetSize();
1876 }
1877};
1878
1879#pragma mark CommandObjectTargetModulesDumpObjfile
1880
1881class CommandObjectTargetModulesDumpObjfile
1882 : public CommandObjectTargetModulesModuleAutoComplete {
1883public:
1884 CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter)
1885 : CommandObjectTargetModulesModuleAutoComplete(
1886 interpreter, "target modules dump objfile",
1887 "Dump the object file headers from one or more target modules.",
1888 nullptr) {}
1889
1890 ~CommandObjectTargetModulesDumpObjfile() override = default;
1891
1892protected:
1893 bool DoExecute(Args &command, CommandReturnObject &result) override {
1894 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1895 if (target == nullptr) {
1896 result.AppendError("invalid target, create a debug target using the "
1897 "'target create' command");
1898 result.SetStatus(eReturnStatusFailed);
1899 return false;
1900 }
1901
1902 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
1903 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
1904 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
1905
1906 size_t num_dumped = 0;
1907 if (command.GetArgumentCount() == 0) {
1908 // Dump all headers for all modules images
1909 num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(),
1910 target->GetImages());
1911 if (num_dumped == 0) {
1912 result.AppendError("the target has no associated executable images");
1913 result.SetStatus(eReturnStatusFailed);
1914 }
1915 } else {
1916 // Find the modules that match the basename or full path.
1917 ModuleList module_list;
1918 const char *arg_cstr;
1919 for (int arg_idx = 0;
1920 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
1921 ++arg_idx) {
1922 size_t num_matched =
1923 FindModulesByName(target, arg_cstr, module_list, true);
1924 if (num_matched == 0) {
1925 result.AppendWarningWithFormat(
1926 "Unable to find an image that matches '%s'.\n", arg_cstr);
1927 }
1928 }
1929 // Dump all the modules we found.
1930 num_dumped =
1931 DumpModuleObjfileHeaders(result.GetOutputStream(), module_list);
1932 }
1933
1934 if (num_dumped > 0) {
1935 result.SetStatus(eReturnStatusSuccessFinishResult);
1936 } else {
1937 result.AppendError("no matching executable images found");
1938 result.SetStatus(eReturnStatusFailed);
1939 }
1940 return result.Succeeded();
1941 }
1942};
1943
1944#pragma mark CommandObjectTargetModulesDumpSymtab
1945
1946static OptionEnumValueElement g_sort_option_enumeration[4] = {
1947 {eSortOrderNone, "none",
1948 "No sorting, use the original symbol table order."},
1949 {eSortOrderByAddress, "address", "Sort output by symbol address."},
1950 {eSortOrderByName, "name", "Sort output by symbol name."},
1951 {0, nullptr, nullptr}};
1952
1953static OptionDefinition g_target_modules_dump_symtab_options[] = {
1954 // clang-format off
1955 { LLDB_OPT_SET_1(1U << 0), false, "sort", 's', OptionParser::eRequiredArgument, nullptr, g_sort_option_enumeration, 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table." }
1956 // clang-format on
1957};
1958
1959class CommandObjectTargetModulesDumpSymtab
1960 : public CommandObjectTargetModulesModuleAutoComplete {
1961public:
1962 CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter)
1963 : CommandObjectTargetModulesModuleAutoComplete(
1964 interpreter, "target modules dump symtab",
1965 "Dump the symbol table from one or more target modules.", nullptr),
1966 m_options() {}
1967
1968 ~CommandObjectTargetModulesDumpSymtab() override = default;
1969
1970 Options *GetOptions() override { return &m_options; }
1971
1972 class CommandOptions : public Options {
1973 public:
1974 CommandOptions() : Options(), m_sort_order(eSortOrderNone) {}
1975
1976 ~CommandOptions() override = default;
1977
1978 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1979 ExecutionContext *execution_context) override {
1980 Status error;
1981 const int short_option = m_getopt_table[option_idx].val;
1982
1983 switch (short_option) {
1984 case 's':
1985 m_sort_order = (SortOrder)Args::StringToOptionEnum(
1986 option_arg, GetDefinitions()[option_idx].enum_values,
1987 eSortOrderNone, error);
1988 break;
1989
1990 default:
1991 error.SetErrorStringWithFormat("invalid short option character '%c'",
1992 short_option);
1993 break;
1994 }
1995 return error;
1996 }
1997
1998 void OptionParsingStarting(ExecutionContext *execution_context) override {
1999 m_sort_order = eSortOrderNone;
2000 }
2001
2002 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2003 return llvm::makeArrayRef(g_target_modules_dump_symtab_options);
2004 }
2005
2006 SortOrder m_sort_order;
2007 };
2008
2009protected:
2010 bool DoExecute(Args &command, CommandReturnObject &result) override {
2011 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2012 if (target == nullptr) {
2013 result.AppendError("invalid target, create a debug target using the "
2014 "'target create' command");
2015 result.SetStatus(eReturnStatusFailed);
2016 return false;
2017 } else {
2018 uint32_t num_dumped = 0;
2019
2020 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2021 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2022 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2023
2024 if (command.GetArgumentCount() == 0) {
2025 // Dump all sections for all modules images
2026 std::lock_guard<std::recursive_mutex> guard(
2027 target->GetImages().GetMutex());
2028 const size_t num_modules = target->GetImages().GetSize();
2029 if (num_modules > 0) {
2030 result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64"l" "u"
2031 " modules.\n",
2032 (uint64_t)num_modules);
2033 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2034 if (num_dumped > 0) {
2035 result.GetOutputStream().EOL();
2036 result.GetOutputStream().EOL();
2037 }
2038 if (m_interpreter.WasInterrupted())
2039 break;
2040 num_dumped++;
2041 DumpModuleSymtab(
2042 m_interpreter, result.GetOutputStream(),
2043 target->GetImages().GetModulePointerAtIndexUnlocked(image_idx),
2044 m_options.m_sort_order);
2045 }
2046 } else {
2047 result.AppendError("the target has no associated executable images");
2048 result.SetStatus(eReturnStatusFailed);
2049 return false;
2050 }
2051 } else {
2052 // Dump specified images (by basename or fullpath)
2053 const char *arg_cstr;
2054 for (int arg_idx = 0;
2055 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2056 ++arg_idx) {
2057 ModuleList module_list;
2058 const size_t num_matches =
2059 FindModulesByName(target, arg_cstr, module_list, true);
2060 if (num_matches > 0) {
2061 for (size_t i = 0; i < num_matches; ++i) {
2062 Module *module = module_list.GetModulePointerAtIndex(i);
2063 if (module) {
2064 if (num_dumped > 0) {
2065 result.GetOutputStream().EOL();
2066 result.GetOutputStream().EOL();
2067 }
2068 if (m_interpreter.WasInterrupted())
2069 break;
2070 num_dumped++;
2071 DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
2072 module, m_options.m_sort_order);
2073 }
2074 }
2075 } else
2076 result.AppendWarningWithFormat(
2077 "Unable to find an image that matches '%s'.\n", arg_cstr);
2078 }
2079 }
2080
2081 if (num_dumped > 0)
2082 result.SetStatus(eReturnStatusSuccessFinishResult);
2083 else {
2084 result.AppendError("no matching executable images found");
2085 result.SetStatus(eReturnStatusFailed);
2086 }
2087 }
2088 return result.Succeeded();
2089 }
2090
2091 CommandOptions m_options;
2092};
2093
2094#pragma mark CommandObjectTargetModulesDumpSections
2095
2096//----------------------------------------------------------------------
2097// Image section dumping command
2098//----------------------------------------------------------------------
2099
2100class CommandObjectTargetModulesDumpSections
2101 : public CommandObjectTargetModulesModuleAutoComplete {
2102public:
2103 CommandObjectTargetModulesDumpSections(CommandInterpreter &interpreter)
2104 : CommandObjectTargetModulesModuleAutoComplete(
2105 interpreter, "target modules dump sections",
2106 "Dump the sections from one or more target modules.",
2107 //"target modules dump sections [<file1> ...]")
2108 nullptr) {}
2109
2110 ~CommandObjectTargetModulesDumpSections() override = default;
2111
2112protected:
2113 bool DoExecute(Args &command, CommandReturnObject &result) override {
2114 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2115 if (target == nullptr) {
2116 result.AppendError("invalid target, create a debug target using the "
2117 "'target create' command");
2118 result.SetStatus(eReturnStatusFailed);
2119 return false;
2120 } else {
2121 uint32_t num_dumped = 0;
2122
2123 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2124 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2125 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2126
2127 if (command.GetArgumentCount() == 0) {
2128 // Dump all sections for all modules images
2129 const size_t num_modules = target->GetImages().GetSize();
2130 if (num_modules > 0) {
2131 result.GetOutputStream().Printf("Dumping sections for %" PRIu64"l" "u"
2132 " modules.\n",
2133 (uint64_t)num_modules);
2134 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2135 if (m_interpreter.WasInterrupted())
2136 break;
2137 num_dumped++;
2138 DumpModuleSections(
2139 m_interpreter, result.GetOutputStream(),
2140 target->GetImages().GetModulePointerAtIndex(image_idx));
2141 }
2142 } else {
2143 result.AppendError("the target has no associated executable images");
2144 result.SetStatus(eReturnStatusFailed);
2145 return false;
2146 }
2147 } else {
2148 // Dump specified images (by basename or fullpath)
2149 const char *arg_cstr;
2150 for (int arg_idx = 0;
2151 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2152 ++arg_idx) {
2153 ModuleList module_list;
2154 const size_t num_matches =
2155 FindModulesByName(target, arg_cstr, module_list, true);
2156 if (num_matches > 0) {
2157 for (size_t i = 0; i < num_matches; ++i) {
2158 if (m_interpreter.WasInterrupted())
2159 break;
2160 Module *module = module_list.GetModulePointerAtIndex(i);
2161 if (module) {
2162 num_dumped++;
2163 DumpModuleSections(m_interpreter, result.GetOutputStream(),
2164 module);
2165 }
2166 }
2167 } else {
2168 // Check the global list
2169 std::lock_guard<std::recursive_mutex> guard(
2170 Module::GetAllocationModuleCollectionMutex());
2171
2172 result.AppendWarningWithFormat(
2173 "Unable to find an image that matches '%s'.\n", arg_cstr);
2174 }
2175 }
2176 }
2177
2178 if (num_dumped > 0)
2179 result.SetStatus(eReturnStatusSuccessFinishResult);
2180 else {
2181 result.AppendError("no matching executable images found");
2182 result.SetStatus(eReturnStatusFailed);
2183 }
2184 }
2185 return result.Succeeded();
2186 }
2187};
2188
2189#pragma mark CommandObjectTargetModulesDumpSymfile
2190
2191//----------------------------------------------------------------------
2192// Image debug symbol dumping command
2193//----------------------------------------------------------------------
2194
2195class CommandObjectTargetModulesDumpSymfile
2196 : public CommandObjectTargetModulesModuleAutoComplete {
2197public:
2198 CommandObjectTargetModulesDumpSymfile(CommandInterpreter &interpreter)
2199 : CommandObjectTargetModulesModuleAutoComplete(
2200 interpreter, "target modules dump symfile",
2201 "Dump the debug symbol file for one or more target modules.",
2202 //"target modules dump symfile [<file1> ...]")
2203 nullptr) {}
2204
2205 ~CommandObjectTargetModulesDumpSymfile() override = default;
2206
2207protected:
2208 bool DoExecute(Args &command, CommandReturnObject &result) override {
2209 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2210 if (target == nullptr) {
2211 result.AppendError("invalid target, create a debug target using the "
2212 "'target create' command");
2213 result.SetStatus(eReturnStatusFailed);
2214 return false;
2215 } else {
2216 uint32_t num_dumped = 0;
2217
2218 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2219 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2220 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2221
2222 if (command.GetArgumentCount() == 0) {
2223 // Dump all sections for all modules images
2224 const ModuleList &target_modules = target->GetImages();
2225 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2226 const size_t num_modules = target_modules.GetSize();
2227 if (num_modules > 0) {
2228 result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64"l" "u"
2229 " modules.\n",
2230 (uint64_t)num_modules);
2231 for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2232 if (m_interpreter.WasInterrupted())
2233 break;
2234 if (DumpModuleSymbolVendor(
2235 result.GetOutputStream(),
2236 target_modules.GetModulePointerAtIndexUnlocked(image_idx)))
2237 num_dumped++;
2238 }
2239 } else {
2240 result.AppendError("the target has no associated executable images");
2241 result.SetStatus(eReturnStatusFailed);
2242 return false;
2243 }
2244 } else {
2245 // Dump specified images (by basename or fullpath)
2246 const char *arg_cstr;
2247 for (int arg_idx = 0;
2248 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2249 ++arg_idx) {
2250 ModuleList module_list;
2251 const size_t num_matches =
2252 FindModulesByName(target, arg_cstr, module_list, true);
2253 if (num_matches > 0) {
2254 for (size_t i = 0; i < num_matches; ++i) {
2255 if (m_interpreter.WasInterrupted())
2256 break;
2257 Module *module = module_list.GetModulePointerAtIndex(i);
2258 if (module) {
2259 if (DumpModuleSymbolVendor(result.GetOutputStream(), module))
2260 num_dumped++;
2261 }
2262 }
2263 } else
2264 result.AppendWarningWithFormat(
2265 "Unable to find an image that matches '%s'.\n", arg_cstr);
2266 }
2267 }
2268
2269 if (num_dumped > 0)
2270 result.SetStatus(eReturnStatusSuccessFinishResult);
2271 else {
2272 result.AppendError("no matching executable images found");
2273 result.SetStatus(eReturnStatusFailed);
2274 }
2275 }
2276 return result.Succeeded();
2277 }
2278};
2279
2280#pragma mark CommandObjectTargetModulesDumpLineTable
2281
2282//----------------------------------------------------------------------
2283// Image debug line table dumping command
2284//----------------------------------------------------------------------
2285
2286class CommandObjectTargetModulesDumpLineTable
2287 : public CommandObjectTargetModulesSourceFileAutoComplete {
2288public:
2289 CommandObjectTargetModulesDumpLineTable(CommandInterpreter &interpreter)
2290 : CommandObjectTargetModulesSourceFileAutoComplete(
2291 interpreter, "target modules dump line-table",
2292 "Dump the line table for one or more compilation units.", nullptr,
2293 eCommandRequiresTarget) {}
2294
2295 ~CommandObjectTargetModulesDumpLineTable() override = default;
2296
2297protected:
2298 bool DoExecute(Args &command, CommandReturnObject &result) override {
2299 Target *target = m_exe_ctx.GetTargetPtr();
2300 uint32_t total_num_dumped = 0;
2301
2302 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2303 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2304 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2305
2306 if (command.GetArgumentCount() == 0) {
2307 result.AppendError("file option must be specified.");
2308 result.SetStatus(eReturnStatusFailed);
2309 return result.Succeeded();
2310 } else {
2311 // Dump specified images (by basename or fullpath)
2312 const char *arg_cstr;
2313 for (int arg_idx = 0;
2314 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2315 ++arg_idx) {
2316 FileSpec file_spec(arg_cstr, false);
2317
2318 const ModuleList &target_modules = target->GetImages();
2319 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2320 const size_t num_modules = target_modules.GetSize();
2321 if (num_modules > 0) {
2322 uint32_t num_dumped = 0;
2323 for (uint32_t i = 0; i < num_modules; ++i) {
2324 if (m_interpreter.WasInterrupted())
2325 break;
2326 if (DumpCompileUnitLineTable(
2327 m_interpreter, result.GetOutputStream(),
2328 target_modules.GetModulePointerAtIndexUnlocked(i),
2329 file_spec, m_exe_ctx.GetProcessPtr() &&
2330 m_exe_ctx.GetProcessRef().IsAlive()))
2331 num_dumped++;
2332 }
2333 if (num_dumped == 0)
2334 result.AppendWarningWithFormat(
2335 "No source filenames matched '%s'.\n", arg_cstr);
2336 else
2337 total_num_dumped += num_dumped;
2338 }
2339 }
2340 }
2341
2342 if (total_num_dumped > 0)
2343 result.SetStatus(eReturnStatusSuccessFinishResult);
2344 else {
2345 result.AppendError("no source filenames matched any command arguments");
2346 result.SetStatus(eReturnStatusFailed);
2347 }
2348 return result.Succeeded();
2349 }
2350};
2351
2352#pragma mark CommandObjectTargetModulesDump
2353
2354//----------------------------------------------------------------------
2355// Dump multi-word command for target modules
2356//----------------------------------------------------------------------
2357
2358class CommandObjectTargetModulesDump : public CommandObjectMultiword {
2359public:
2360 //------------------------------------------------------------------
2361 // Constructors and Destructors
2362 //------------------------------------------------------------------
2363 CommandObjectTargetModulesDump(CommandInterpreter &interpreter)
2364 : CommandObjectMultiword(interpreter, "target modules dump",
2365 "Commands for dumping information about one or "
2366 "more target modules.",
2367 "target modules dump "
2368 "[headers|symtab|sections|symfile|line-table] "
2369 "[<file1> <file2> ...]") {
2370 LoadSubCommand("objfile",
2371 CommandObjectSP(
2372 new CommandObjectTargetModulesDumpObjfile(interpreter)));
2373 LoadSubCommand(
2374 "symtab",
2375 CommandObjectSP(new CommandObjectTargetModulesDumpSymtab(interpreter)));
2376 LoadSubCommand("sections",
2377 CommandObjectSP(new CommandObjectTargetModulesDumpSections(
2378 interpreter)));
2379 LoadSubCommand("symfile",
2380 CommandObjectSP(
2381 new CommandObjectTargetModulesDumpSymfile(interpreter)));
2382 LoadSubCommand("line-table",
2383 CommandObjectSP(new CommandObjectTargetModulesDumpLineTable(
2384 interpreter)));
2385 }
2386
2387 ~CommandObjectTargetModulesDump() override = default;
2388};
2389
2390class CommandObjectTargetModulesAdd : public CommandObjectParsed {
2391public:
2392 CommandObjectTargetModulesAdd(CommandInterpreter &interpreter)
2393 : CommandObjectParsed(interpreter, "target modules add",
2394 "Add a new module to the current target's modules.",
2395 "target modules add [<module>]"),
2396 m_option_group(),
2397 m_symbol_file(LLDB_OPT_SET_1(1U << 0), false, "symfile", 's', 0,
2398 eArgTypeFilename, "Fullpath to a stand alone debug "
2399 "symbols file for when debug symbols "
2400 "are not in the executable.") {
2401 m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL0xFFFFFFFFU,
2402 LLDB_OPT_SET_1(1U << 0));
2403 m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
2404 m_option_group.Finalize();
2405 }
2406
2407 ~CommandObjectTargetModulesAdd() override = default;
2408
2409 Options *GetOptions() override { return &m_option_group; }
2410
2411 int HandleArgumentCompletion(Args &input, int &cursor_index,
2412 int &cursor_char_position,
2413 OptionElementVector &opt_element_vector,
2414 int match_start_point, int max_return_elements,
2415 bool &word_complete,
2416 StringList &matches) override {
2417 std::string completion_str(input.GetArgumentAtIndex(cursor_index));
2418 completion_str.erase(cursor_char_position);
2419
2420 CommandCompletions::InvokeCommonCompletionCallbacks(
2421 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
2422 completion_str.c_str(), match_start_point, max_return_elements, nullptr,
2423 word_complete, matches);
2424 return matches.GetSize();
2425 }
2426
2427protected:
2428 OptionGroupOptions m_option_group;
2429 OptionGroupUUID m_uuid_option_group;
2430 OptionGroupFile m_symbol_file;
2431
2432 bool DoExecute(Args &args, CommandReturnObject &result) override {
2433 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2434 if (target == nullptr) {
2435 result.AppendError("invalid target, create a debug target using the "
2436 "'target create' command");
2437 result.SetStatus(eReturnStatusFailed);
2438 return false;
2439 } else {
2440 bool flush = false;
2441
2442 const size_t argc = args.GetArgumentCount();
2443 if (argc == 0) {
2444 if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2445 // We are given a UUID only, go locate the file
2446 ModuleSpec module_spec;
2447 module_spec.GetUUID() =
2448 m_uuid_option_group.GetOptionValue().GetCurrentValue();
2449 if (m_symbol_file.GetOptionValue().OptionWasSet())
2450 module_spec.GetSymbolFileSpec() =
2451 m_symbol_file.GetOptionValue().GetCurrentValue();
2452 if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
2453 ModuleSP module_sp(target->GetSharedModule(module_spec));
2454 if (module_sp) {
2455 result.SetStatus(eReturnStatusSuccessFinishResult);
2456 return true;
2457 } else {
2458 StreamString strm;
2459 module_spec.GetUUID().Dump(&strm);
2460 if (module_spec.GetFileSpec()) {
2461 if (module_spec.GetSymbolFileSpec()) {
2462 result.AppendErrorWithFormat(
2463 "Unable to create the executable or symbol file with "
2464 "UUID %s with path %s and symbol file %s",
2465 strm.GetData(),
2466 module_spec.GetFileSpec().GetPath().c_str(),
2467 module_spec.GetSymbolFileSpec().GetPath().c_str());
2468 } else {
2469 result.AppendErrorWithFormat(
2470 "Unable to create the executable or symbol file with "
2471 "UUID %s with path %s",
2472 strm.GetData(),
2473 module_spec.GetFileSpec().GetPath().c_str());
2474 }
2475 } else {
2476 result.AppendErrorWithFormat("Unable to create the executable "
2477 "or symbol file with UUID %s",
2478 strm.GetData());
2479 }
2480 result.SetStatus(eReturnStatusFailed);
2481 return false;
2482 }
2483 } else {
2484 StreamString strm;
2485 module_spec.GetUUID().Dump(&strm);
2486 result.AppendErrorWithFormat(
2487 "Unable to locate the executable or symbol file with UUID %s",
2488 strm.GetData());
2489 result.SetStatus(eReturnStatusFailed);
2490 return false;
2491 }
2492 } else {
2493 result.AppendError(
2494 "one or more executable image paths must be specified");
2495 result.SetStatus(eReturnStatusFailed);
2496 return false;
2497 }
2498 } else {
2499 for (auto &entry : args.entries()) {
2500 if (entry.ref.empty())
2501 continue;
2502
2503 FileSpec file_spec(entry.ref, true);
2504 if (file_spec.Exists()) {
2505 ModuleSpec module_spec(file_spec);
2506 if (m_uuid_option_group.GetOptionValue().OptionWasSet())
2507 module_spec.GetUUID() =
2508 m_uuid_option_group.GetOptionValue().GetCurrentValue();
2509 if (m_symbol_file.GetOptionValue().OptionWasSet())
2510 module_spec.GetSymbolFileSpec() =
2511 m_symbol_file.GetOptionValue().GetCurrentValue();
2512 if (!module_spec.GetArchitecture().IsValid())
2513 module_spec.GetArchitecture() = target->GetArchitecture();
2514 Status error;
2515 ModuleSP module_sp(target->GetSharedModule(module_spec, &error));
2516 if (!module_sp) {
2517 const char *error_cstr = error.AsCString();
2518 if (error_cstr)
2519 result.AppendError(error_cstr);
2520 else
2521 result.AppendErrorWithFormat("unsupported module: %s",
2522 entry.c_str());
2523 result.SetStatus(eReturnStatusFailed);
2524 return false;
2525 } else {
2526 flush = true;
2527 }
2528 result.SetStatus(eReturnStatusSuccessFinishResult);
2529 } else {
2530 std::string resolved_path = file_spec.GetPath();
2531 result.SetStatus(eReturnStatusFailed);
2532 if (resolved_path != entry.ref) {
2533 result.AppendErrorWithFormat(
2534 "invalid module path '%s' with resolved path '%s'\n",
2535 entry.ref.str().c_str(), resolved_path.c_str());
2536 break;
2537 }
2538 result.AppendErrorWithFormat("invalid module path '%s'\n",
2539 entry.c_str());
2540 break;
2541 }
2542 }
2543 }
2544
2545 if (flush) {
2546 ProcessSP process = target->GetProcessSP();
2547 if (process)
2548 process->Flush();
2549 }
2550 }
2551
2552 return result.Succeeded();
2553 }
2554};
2555
2556class CommandObjectTargetModulesLoad
2557 : public CommandObjectTargetModulesModuleAutoComplete {
2558public:
2559 CommandObjectTargetModulesLoad(CommandInterpreter &interpreter)
2560 : CommandObjectTargetModulesModuleAutoComplete(
2561 interpreter, "target modules load", "Set the load addresses for "
2562 "one or more sections in a "
2563 "target module.",
2564 "target modules load [--file <module> --uuid <uuid>] <sect-name> "
2565 "<address> [<sect-name> <address> ....]"),
2566 m_option_group(),
2567 m_file_option(LLDB_OPT_SET_1(1U << 0), false, "file", 'f', 0, eArgTypeName,
2568 "Fullpath or basename for module to load.", ""),
2569 m_load_option(LLDB_OPT_SET_1(1U << 0), false, "load", 'l',
2570 "Write file contents to the memory.", false, true),
2571 m_pc_option(LLDB_OPT_SET_1(1U << 0), false, "set-pc-to-entry", 'p',
2572 "Set PC to the entry point."
2573 " Only applicable with '--load' option.",
2574 false, true),
2575 m_slide_option(LLDB_OPT_SET_1(1U << 0), false, "slide", 's', 0, eArgTypeOffset,
2576 "Set the load address for all sections to be the "
2577 "virtual address in the file plus the offset.",
2578 0) {
2579 m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL0xFFFFFFFFU,
2580 LLDB_OPT_SET_1(1U << 0));
2581 m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
2582 m_option_group.Append(&m_load_option, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
2583 m_option_group.Append(&m_pc_option, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
2584 m_option_group.Append(&m_slide_option, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
2585 m_option_group.Finalize();
2586 }
2587
2588 ~CommandObjectTargetModulesLoad() override = default;
2589
2590 Options *GetOptions() override { return &m_option_group; }
2591
2592protected:
2593 bool DoExecute(Args &args, CommandReturnObject &result) override {
2594 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2595 const bool load = m_load_option.GetOptionValue().GetCurrentValue();
2596 const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue();
2597 if (target == nullptr) {
2598 result.AppendError("invalid target, create a debug target using the "
2599 "'target create' command");
2600 result.SetStatus(eReturnStatusFailed);
2601 return false;
2602 } else {
2603 const size_t argc = args.GetArgumentCount();
2604 ModuleSpec module_spec;
2605 bool search_using_module_spec = false;
2606
2607 // Allow "load" option to work without --file or --uuid
2608 // option.
2609 if (load) {
2610 if (!m_file_option.GetOptionValue().OptionWasSet() &&
2611 !m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2612 ModuleList &module_list = target->GetImages();
2613 if (module_list.GetSize() == 1) {
2614 search_using_module_spec = true;
2615 module_spec.GetFileSpec() =
2616 module_list.GetModuleAtIndex(0)->GetFileSpec();
2617 }
2618 }
2619 }
2620
2621 if (m_file_option.GetOptionValue().OptionWasSet()) {
2622 search_using_module_spec = true;
2623 const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue();
2624 const bool use_global_module_list = true;
2625 ModuleList module_list;
2626 const size_t num_matches = FindModulesByName(
2627 target, arg_cstr, module_list, use_global_module_list);
2628 if (num_matches == 1) {
2629 module_spec.GetFileSpec() =
2630 module_list.GetModuleAtIndex(0)->GetFileSpec();
2631 } else if (num_matches > 1) {
2632 search_using_module_spec = false;
2633 result.AppendErrorWithFormat(
2634 "more than 1 module matched by name '%s'\n", arg_cstr);
2635 result.SetStatus(eReturnStatusFailed);
2636 } else {
2637 search_using_module_spec = false;
2638 result.AppendErrorWithFormat("no object file for module '%s'\n",
2639 arg_cstr);
2640 result.SetStatus(eReturnStatusFailed);
2641 }
2642 }
2643
2644 if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2645 search_using_module_spec = true;
2646 module_spec.GetUUID() =
2647 m_uuid_option_group.GetOptionValue().GetCurrentValue();
2648 }
2649
2650 if (search_using_module_spec) {
2651 ModuleList matching_modules;
2652 const size_t num_matches =
2653 target->GetImages().FindModules(module_spec, matching_modules);
2654
2655 char path[PATH_MAX4096];
2656 if (num_matches == 1) {
2657 Module *module = matching_modules.GetModulePointerAtIndex(0);
2658 if (module) {
2659 ObjectFile *objfile = module->GetObjectFile();
2660 if (objfile) {
2661 SectionList *section_list = module->GetSectionList();
2662 if (section_list) {
2663 bool changed = false;
2664 if (argc == 0) {
2665 if (m_slide_option.GetOptionValue().OptionWasSet()) {
2666 const addr_t slide =
2667 m_slide_option.GetOptionValue().GetCurrentValue();
2668 const bool slide_is_offset = true;
2669 module->SetLoadAddress(*target, slide, slide_is_offset,
2670 changed);
2671 } else {
2672 result.AppendError("one or more section name + load "
2673 "address pair must be specified");
2674 result.SetStatus(eReturnStatusFailed);
2675 return false;
2676 }
2677 } else {
2678 if (m_slide_option.GetOptionValue().OptionWasSet()) {
2679 result.AppendError("The \"--slide <offset>\" option can't "
2680 "be used in conjunction with setting "
2681 "section load addresses.\n");
2682 result.SetStatus(eReturnStatusFailed);
2683 return false;
2684 }
2685
2686 for (size_t i = 0; i < argc; i += 2) {
2687 const char *sect_name = args.GetArgumentAtIndex(i);
2688 const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1);
2689 if (sect_name && load_addr_cstr) {
2690 ConstString const_sect_name(sect_name);
2691 bool success = false;
2692 addr_t load_addr = StringConvert::ToUInt64(
2693 load_addr_cstr, LLDB_INVALID_ADDRESS(18446744073709551615UL), 0, &success);
2694 if (success) {
2695 SectionSP section_sp(
2696 section_list->FindSectionByName(const_sect_name));
2697 if (section_sp) {
2698 if (section_sp->IsThreadSpecific()) {
2699 result.AppendErrorWithFormat(
2700 "thread specific sections are not yet "
2701 "supported (section '%s')\n",
2702 sect_name);
2703 result.SetStatus(eReturnStatusFailed);
2704 break;
2705 } else {
2706 if (target->GetSectionLoadList()
2707 .SetSectionLoadAddress(section_sp,
2708 load_addr))
2709 changed = true;
2710 result.AppendMessageWithFormat(
2711 "section '%s' loaded at 0x%" PRIx64"l" "x" "\n",
2712 sect_name, load_addr);
2713 }
2714 } else {
2715 result.AppendErrorWithFormat("no section found that "
2716 "matches the section "
2717 "name '%s'\n",
2718 sect_name);
2719 result.SetStatus(eReturnStatusFailed);
2720 break;
2721 }
2722 } else {
2723 result.AppendErrorWithFormat(
2724 "invalid load address string '%s'\n",
2725 load_addr_cstr);
2726 result.SetStatus(eReturnStatusFailed);
2727 break;
2728 }
2729 } else {
2730 if (sect_name)
2731 result.AppendError("section names must be followed by "
2732 "a load address.\n");
2733 else
2734 result.AppendError("one or more section name + load "
2735 "address pair must be specified.\n");
2736 result.SetStatus(eReturnStatusFailed);
2737 break;
2738 }
2739 }
2740 }
2741
2742 if (changed) {
2743 target->ModulesDidLoad(matching_modules);
2744 Process *process = m_exe_ctx.GetProcessPtr();
2745 if (process)
2746 process->Flush();
2747 }
2748 if (load) {
2749 Status error = module->LoadInMemory(*target, set_pc);
2750 if (error.Fail()) {
2751 result.AppendError(error.AsCString());
2752 return false;
2753 }
2754 }
2755 } else {
2756 module->GetFileSpec().GetPath(path, sizeof(path));
2757 result.AppendErrorWithFormat(
2758 "no sections in object file '%s'\n", path);
2759 result.SetStatus(eReturnStatusFailed);
2760 }
2761 } else {
2762 module->GetFileSpec().GetPath(path, sizeof(path));
2763 result.AppendErrorWithFormat("no object file for module '%s'\n",
2764 path);
2765 result.SetStatus(eReturnStatusFailed);
2766 }
2767 } else {
2768 FileSpec *module_spec_file = module_spec.GetFileSpecPtr();
2769 if (module_spec_file) {
2770 module_spec_file->GetPath(path, sizeof(path));
2771 result.AppendErrorWithFormat("invalid module '%s'.\n", path);
2772 } else
2773 result.AppendError("no module spec");
2774 result.SetStatus(eReturnStatusFailed);
2775 }
2776 } else {
2777 std::string uuid_str;
2778
2779 if (module_spec.GetFileSpec())
2780 module_spec.GetFileSpec().GetPath(path, sizeof(path));
2781 else
2782 path[0] = '\0';
2783
2784 if (module_spec.GetUUIDPtr())
2785 uuid_str = module_spec.GetUUID().GetAsString();
2786 if (num_matches > 1) {
2787 result.AppendErrorWithFormat(
2788 "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "",
2789 path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
2790 for (size_t i = 0; i < num_matches; ++i) {
2791 if (matching_modules.GetModulePointerAtIndex(i)
2792 ->GetFileSpec()
2793 .GetPath(path, sizeof(path)))
2794 result.AppendMessageWithFormat("%s\n", path);
2795 }
2796 } else {
2797 result.AppendErrorWithFormat(
2798 "no modules were found that match%s%s%s%s.\n",
2799 path[0] ? " file=" : "", path,
2800 !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
2801 }
2802 result.SetStatus(eReturnStatusFailed);
2803 }
2804 } else {
2805 result.AppendError("either the \"--file <module>\" or the \"--uuid "
2806 "<uuid>\" option must be specified.\n");
2807 result.SetStatus(eReturnStatusFailed);
2808 return false;
2809 }
2810 }
2811 return result.Succeeded();
2812 }
2813
2814 OptionGroupOptions m_option_group;
2815 OptionGroupUUID m_uuid_option_group;
2816 OptionGroupString m_file_option;
2817 OptionGroupBoolean m_load_option;
2818 OptionGroupBoolean m_pc_option;
2819 OptionGroupUInt64 m_slide_option;
2820};
2821
2822//----------------------------------------------------------------------
2823// List images with associated information
2824//----------------------------------------------------------------------
2825
2826static OptionDefinition g_target_modules_list_options[] = {
2827 // clang-format off
2828 { LLDB_OPT_SET_1(1U << 0), false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Display the image at this address." },
2829 { LLDB_OPT_SET_1(1U << 0), false, "arch", 'A', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the architecture when listing images." },
2830 { LLDB_OPT_SET_1(1U << 0), false, "triple", 't', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the triple when listing images." },
2831 { LLDB_OPT_SET_1(1U << 0), false, "header", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the image header address as a load address if debugging, a file address otherwise." },
2832 { LLDB_OPT_SET_1(1U << 0), false, "offset", 'o', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the image header address offset from the header file address (the slide amount)." },
2833 { LLDB_OPT_SET_1(1U << 0), false, "uuid", 'u', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the UUID when listing images." },
2834 { LLDB_OPT_SET_1(1U << 0), false, "fullpath", 'f', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the fullpath to the image object file." },
2835 { LLDB_OPT_SET_1(1U << 0), false, "directory", 'd', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the directory with optional width for the image object file." },
2836 { LLDB_OPT_SET_1(1U << 0), false, "basename", 'b', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the basename with optional width for the image object file." },
2837 { LLDB_OPT_SET_1(1U << 0), false, "symfile", 's', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width." },
2838 { LLDB_OPT_SET_1(1U << 0), false, "symfile-unique", 'S', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the symbol file with optional width only if it is different from the executable object file." },
2839 { LLDB_OPT_SET_1(1U << 0), false, "mod-time", 'm', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the modification time with optional width of the module." },
2840 { LLDB_OPT_SET_1(1U << 0), false, "ref-count", 'r', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the reference count if the module is still in the shared module cache." },
2841 { LLDB_OPT_SET_1(1U << 0), false, "pointer", 'p', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the module pointer." },
2842 { LLDB_OPT_SET_1(1U << 0), false, "global", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the modules from the global module list, not just the current target." }
2843 // clang-format on
2844};
2845
2846class CommandObjectTargetModulesList : public CommandObjectParsed {
2847public:
2848 class CommandOptions : public Options {
2849 public:
2850 CommandOptions()
2851 : Options(), m_format_array(), m_use_global_module_list(false),
2852 m_module_addr(LLDB_INVALID_ADDRESS(18446744073709551615UL)) {}
2853
2854 ~CommandOptions() override = default;
2855
2856 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2857 ExecutionContext *execution_context) override {
2858 Status error;
2859
2860 const int short_option = m_getopt_table[option_idx].val;
2861 if (short_option == 'g') {
2862 m_use_global_module_list = true;
2863 } else if (short_option == 'a') {
2864 m_module_addr = Args::StringToAddress(execution_context, option_arg,
2865 LLDB_INVALID_ADDRESS(18446744073709551615UL), &error);
2866 } else {
2867 unsigned long width = 0;
2868 option_arg.getAsInteger(0, width);
2869 m_format_array.push_back(std::make_pair(short_option, width));
2870 }
2871 return error;
2872 }
2873
2874 void OptionParsingStarting(ExecutionContext *execution_context) override {
2875 m_format_array.clear();
2876 m_use_global_module_list = false;
2877 m_module_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL);
2878 }
2879
2880 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2881 return llvm::makeArrayRef(g_target_modules_list_options);
2882 }
2883
2884 // Instance variables to hold the values for command options.
2885 typedef std::vector<std::pair<char, uint32_t>> FormatWidthCollection;
2886 FormatWidthCollection m_format_array;
2887 bool m_use_global_module_list;
2888 lldb::addr_t m_module_addr;
2889 };
2890
2891 CommandObjectTargetModulesList(CommandInterpreter &interpreter)
2892 : CommandObjectParsed(
2893 interpreter, "target modules list",
2894 "List current executable and dependent shared library images.",
2895 "target modules list [<cmd-options>]"),
2896 m_options() {}
2897
2898 ~CommandObjectTargetModulesList() override = default;
2899
2900 Options *GetOptions() override { return &m_options; }
2901
2902protected:
2903 bool DoExecute(Args &command, CommandReturnObject &result) override {
2904 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2905 const bool use_global_module_list = m_options.m_use_global_module_list;
2906 // Define a local module list here to ensure it lives longer than any
2907 // "locker"
2908 // object which might lock its contents below (through the "module_list_ptr"
2909 // variable).
2910 ModuleList module_list;
2911 if (target == nullptr && !use_global_module_list) {
2912 result.AppendError("invalid target, create a debug target using the "
2913 "'target create' command");
2914 result.SetStatus(eReturnStatusFailed);
2915 return false;
2916 } else {
2917 if (target) {
2918 uint32_t addr_byte_size =
2919 target->GetArchitecture().GetAddressByteSize();
2920 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2921 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2922 }
2923 // Dump all sections for all modules images
2924 Stream &strm = result.GetOutputStream();
2925
2926 if (m_options.m_module_addr != LLDB_INVALID_ADDRESS(18446744073709551615UL)) {
2927 if (target) {
2928 Address module_address;
2929 if (module_address.SetLoadAddress(m_options.m_module_addr, target)) {
2930 ModuleSP module_sp(module_address.GetModule());
2931 if (module_sp) {
2932 PrintModule(target, module_sp.get(), 0, strm);
2933 result.SetStatus(eReturnStatusSuccessFinishResult);
2934 } else {
2935 result.AppendErrorWithFormat(
2936 "Couldn't find module matching address: 0x%" PRIx64"l" "x" ".",
2937 m_options.m_module_addr);
2938 result.SetStatus(eReturnStatusFailed);
2939 }
2940 } else {
2941 result.AppendErrorWithFormat(
2942 "Couldn't find module containing address: 0x%" PRIx64"l" "x" ".",
2943 m_options.m_module_addr);
2944 result.SetStatus(eReturnStatusFailed);
2945 }
2946 } else {
2947 result.AppendError(
2948 "Can only look up modules by address with a valid target.");
2949 result.SetStatus(eReturnStatusFailed);
2950 }
2951 return result.Succeeded();
2952 }
2953
2954 size_t num_modules = 0;
2955
2956 // This locker will be locked on the mutex in module_list_ptr if it is
2957 // non-nullptr.
2958 // Otherwise it will lock the AllocationModuleCollectionMutex when
2959 // accessing
2960 // the global module list directly.
2961 std::unique_lock<std::recursive_mutex> guard(
2962 Module::GetAllocationModuleCollectionMutex(), std::defer_lock);
2963
2964 const ModuleList *module_list_ptr = nullptr;
2965 const size_t argc = command.GetArgumentCount();
2966 if (argc == 0) {
2967 if (use_global_module_list) {
2968 guard.lock();
2969 num_modules = Module::GetNumberAllocatedModules();
2970 } else {
2971 module_list_ptr = &target->GetImages();
2972 }
2973 } else {
2974 // TODO: Convert to entry based iteration. Requires converting
2975 // FindModulesByName.
2976 for (size_t i = 0; i < argc; ++i) {
2977 // Dump specified images (by basename or fullpath)
2978 const char *arg_cstr = command.GetArgumentAtIndex(i);
2979 const size_t num_matches = FindModulesByName(
2980 target, arg_cstr, module_list, use_global_module_list);
2981 if (num_matches == 0) {
2982 if (argc == 1) {
2983 result.AppendErrorWithFormat("no modules found that match '%s'",
2984 arg_cstr);
2985 result.SetStatus(eReturnStatusFailed);
2986 return false;
2987 }
2988 }
2989 }
2990
2991 module_list_ptr = &module_list;
2992 }
2993
2994 std::unique_lock<std::recursive_mutex> lock;
2995 if (module_list_ptr != nullptr) {
2996 lock =
2997 std::unique_lock<std::recursive_mutex>(module_list_ptr->GetMutex());
2998
2999 num_modules = module_list_ptr->GetSize();
3000 }
3001
3002 if (num_modules > 0) {
3003 for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
3004 ModuleSP module_sp;
3005 Module *module;
3006 if (module_list_ptr) {
3007 module_sp = module_list_ptr->GetModuleAtIndexUnlocked(image_idx);
3008 module = module_sp.get();
3009 } else {
3010 module = Module::GetAllocatedModuleAtIndex(image_idx);
3011 module_sp = module->shared_from_this();
3012 }
3013
3014 const size_t indent = strm.Printf("[%3u] ", image_idx);
3015 PrintModule(target, module, indent, strm);
3016 }
3017 result.SetStatus(eReturnStatusSuccessFinishResult);
3018 } else {
3019 if (argc) {
3020 if (use_global_module_list)
3021 result.AppendError(
3022 "the global module list has no matching modules");
3023 else
3024 result.AppendError("the target has no matching modules");
3025 } else {
3026 if (use_global_module_list)
3027 result.AppendError("the global module list is empty");
3028 else
3029 result.AppendError(
3030 "the target has no associated executable images");
3031 }
3032 result.SetStatus(eReturnStatusFailed);
3033 return false;
3034 }
3035 }
3036 return result.Succeeded();
3037 }
3038
3039 void PrintModule(Target *target, Module *module, int indent, Stream &strm) {
3040 if (module == nullptr) {
3041 strm.PutCString("Null module");
3042 return;
3043 }
3044
3045 bool dump_object_name = false;
3046 if (m_options.m_format_array.empty()) {
3047 m_options.m_format_array.push_back(std::make_pair('u', 0));
3048 m_options.m_format_array.push_back(std::make_pair('h', 0));
3049 m_options.m_format_array.push_back(std::make_pair('f', 0));
3050 m_options.m_format_array.push_back(std::make_pair('S', 0));
3051 }
3052 const size_t num_entries = m_options.m_format_array.size();
3053 bool print_space = false;
3054 for (size_t i = 0; i < num_entries; ++i) {
3055 if (print_space)
3056 strm.PutChar(' ');
3057 print_space = true;
3058 const char format_char = m_options.m_format_array[i].first;
3059 uint32_t width = m_options.m_format_array[i].second;
3060 switch (format_char) {
3061 case 'A':
3062 DumpModuleArchitecture(strm, module, false, width);
3063 break;
3064
3065 case 't':
3066 DumpModuleArchitecture(strm, module, true, width);
3067 break;
3068
3069 case 'f':
3070 DumpFullpath(strm, &module->GetFileSpec(), width);
3071 dump_object_name = true;
3072 break;
3073
3074 case 'd':
3075 DumpDirectory(strm, &module->GetFileSpec(), width);
3076 break;
3077
3078 case 'b':
3079 DumpBasename(strm, &module->GetFileSpec(), width);
3080 dump_object_name = true;
3081 break;
3082
3083 case 'h':
3084 case 'o':
3085 // Image header address
3086 {
3087 uint32_t addr_nibble_width =
3088 target ? (target->GetArchitecture().GetAddressByteSize() * 2)
3089 : 16;
3090
3091 ObjectFile *objfile = module->GetObjectFile();
3092 if (objfile) {
3093 Address header_addr(objfile->GetHeaderAddress());
3094 if (header_addr.IsValid()) {
3095 if (target && !target->GetSectionLoadList().IsEmpty()) {
3096 lldb::addr_t header_load_addr =
3097 header_addr.GetLoadAddress(target);
3098 if (header_load_addr == LLDB_INVALID_ADDRESS(18446744073709551615UL)) {
3099 header_addr.Dump(&strm, target,
3100 Address::DumpStyleModuleWithFileAddress,
3101 Address::DumpStyleFileAddress);
3102 } else {
3103 if (format_char == 'o') {
3104 // Show the offset of slide for the image
3105 strm.Printf(
3106 "0x%*.*" PRIx64"l" "x", addr_nibble_width, addr_nibble_width,
3107 header_load_addr - header_addr.GetFileAddress());
3108 } else {
3109 // Show the load address of the image
3110 strm.Printf("0x%*.*" PRIx64"l" "x", addr_nibble_width,
3111 addr_nibble_width, header_load_addr);
3112 }
3113 }
3114 break;
3115 }
3116 // The address was valid, but the image isn't loaded, output the
3117 // address in an appropriate format
3118 header_addr.Dump(&strm, target, Address::DumpStyleFileAddress);
3119 break;
3120 }
3121 }
3122 strm.Printf("%*s", addr_nibble_width + 2, "");
3123 }
3124 break;
3125
3126 case 'r': {
3127 size_t ref_count = 0;
3128 ModuleSP module_sp(module->shared_from_this());
3129 if (module_sp) {
3130 // Take one away to make sure we don't count our local "module_sp"
3131 ref_count = module_sp.use_count() - 1;
3132 }
3133 if (width)
3134 strm.Printf("{%*" PRIu64"l" "u" "}", width, (uint64_t)ref_count);
3135 else
3136 strm.Printf("{%" PRIu64"l" "u" "}", (uint64_t)ref_count);
3137 } break;
3138
3139 case 's':
3140 case 'S': {
3141 const SymbolVendor *symbol_vendor = module->GetSymbolVendor();
3142 if (symbol_vendor) {
3143 const FileSpec symfile_spec = symbol_vendor->GetMainFileSpec();
3144 if (format_char == 'S') {
3145 // Dump symbol file only if different from module file
3146 if (!symfile_spec || symfile_spec == module->GetFileSpec()) {
3147 print_space = false;
3148 break;
3149 }
3150 // Add a newline and indent past the index
3151 strm.Printf("\n%*s", indent, "");
3152 }
3153 DumpFullpath(strm, &symfile_spec, width);
3154 dump_object_name = true;
3155 break;
3156 }
3157 strm.Printf("%.*s", width, "<NONE>");
3158 } break;
3159
3160 case 'm':
3161 strm.Format("{0:%c}", llvm::fmt_align(module->GetModificationTime(),
3162 llvm::AlignStyle::Left, width));
3163 break;
3164
3165 case 'p':
3166 strm.Printf("%p", static_cast<void *>(module));
3167 break;
3168
3169 case 'u':
3170 DumpModuleUUID(strm, module);
3171 break;
3172
3173 default:
3174 break;
3175 }
3176 }
3177 if (dump_object_name) {
3178 const char *object_name = module->GetObjectName().GetCString();
3179 if (object_name)
3180 strm.Printf("(%s)", object_name);
3181 }
3182 strm.EOL();
3183 }
3184
3185 CommandOptions m_options;
3186};
3187
3188#pragma mark CommandObjectTargetModulesShowUnwind
3189
3190//----------------------------------------------------------------------
3191// Lookup unwind information in images
3192//----------------------------------------------------------------------
3193
3194static OptionDefinition g_target_modules_show_unwind_options[] = {
3195 // clang-format off
3196 { LLDB_OPT_SET_1(1U << 0), false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFunctionName, "Show unwind instructions for a function or symbol name." },
3197 { LLDB_OPT_SET_2(1U << 1), false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address" }
3198 // clang-format on
3199};
3200
3201class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {
3202public:
3203 enum {
3204 eLookupTypeInvalid = -1,
3205 eLookupTypeAddress = 0,
3206 eLookupTypeSymbol,
3207 eLookupTypeFunction,
3208 eLookupTypeFunctionOrSymbol,
3209 kNumLookupTypes
3210 };
3211
3212 class CommandOptions : public Options {
3213 public:
3214 CommandOptions()
3215 : Options(), m_type(eLookupTypeInvalid), m_str(),
3216 m_addr(LLDB_INVALID_ADDRESS(18446744073709551615UL)) {}
3217
3218 ~CommandOptions() override = default;
3219
3220 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3221 ExecutionContext *execution_context) override {
3222 Status error;
3223
3224 const int short_option = m_getopt_table[option_idx].val;
3225
3226 switch (short_option) {
3227 case 'a': {
3228 m_str = option_arg;
3229 m_type = eLookupTypeAddress;
3230 m_addr = Args::StringToAddress(execution_context, option_arg,
3231 LLDB_INVALID_ADDRESS(18446744073709551615UL), &error);
3232 if (m_addr == LLDB_INVALID_ADDRESS(18446744073709551615UL))
3233 error.SetErrorStringWithFormat("invalid address string '%s'",
3234 option_arg.str().c_str());
3235 break;
3236 }
3237
3238 case 'n':
3239 m_str = option_arg;
3240 m_type = eLookupTypeFunctionOrSymbol;
3241 break;
3242
3243 default:
3244 error.SetErrorStringWithFormat("unrecognized option %c.", short_option);
3245 break;
3246 }
3247
3248 return error;
3249 }
3250
3251 void OptionParsingStarting(ExecutionContext *execution_context) override {
3252 m_type = eLookupTypeInvalid;
3253 m_str.clear();
3254 m_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL);
3255 }
3256
3257 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3258 return llvm::makeArrayRef(g_target_modules_show_unwind_options);
3259 }
3260
3261 // Instance variables to hold the values for command options.
3262
3263 int m_type; // Should be a eLookupTypeXXX enum after parsing options
3264 std::string m_str; // Holds name lookup
3265 lldb::addr_t m_addr; // Holds the address to lookup
3266 };
3267
3268 CommandObjectTargetModulesShowUnwind(CommandInterpreter &interpreter)
3269 : CommandObjectParsed(
3270 interpreter, "target modules show-unwind",
3271 "Show synthesized unwind instructions for a function.", nullptr,
3272 eCommandRequiresTarget | eCommandRequiresProcess |
3273 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
3274 m_options() {}
3275
3276 ~CommandObjectTargetModulesShowUnwind() override = default;
3277
3278 Options *GetOptions() override { return &m_options; }
3279
3280protected:
3281 bool DoExecute(Args &command, CommandReturnObject &result) override {
3282 Target *target = m_exe_ctx.GetTargetPtr();
3283 Process *process = m_exe_ctx.GetProcessPtr();
3284 ABI *abi = nullptr;
3285 if (process)
3286 abi = process->GetABI().get();
3287
3288 if (process == nullptr) {
3289 result.AppendError(
3290 "You must have a process running to use this command.");
3291 result.SetStatus(eReturnStatusFailed);
3292 return false;
3293 }
3294
3295 ThreadList threads(process->GetThreadList());
3296 if (threads.GetSize() == 0) {
3297 result.AppendError("The process must be paused to use this command.");
3298 result.SetStatus(eReturnStatusFailed);
3299 return false;
3300 }
3301
3302 ThreadSP thread(threads.GetThreadAtIndex(0));
3303 if (!thread) {
3304 result.AppendError("The process must be paused to use this command.");
3305 result.SetStatus(eReturnStatusFailed);
3306 return false;
3307 }
3308
3309 SymbolContextList sc_list;
3310
3311 if (m_options.m_type == eLookupTypeFunctionOrSymbol) {
3312 ConstString function_name(m_options.m_str.c_str());
3313 target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto,
3314 true, false, true, sc_list);
3315 } else if (m_options.m_type == eLookupTypeAddress && target) {
3316 Address addr;
3317 if (target->GetSectionLoadList().ResolveLoadAddress(m_options.m_addr,
3318 addr)) {
3319 SymbolContext sc;
3320 ModuleSP module_sp(addr.GetModule());
3321 module_sp->ResolveSymbolContextForAddress(addr,
3322 eSymbolContextEverything, sc);
3323 if (sc.function || sc.symbol) {
3324 sc_list.Append(sc);
3325 }
3326 }
3327 } else {
3328 result.AppendError(
3329 "address-expression or function name option must be specified.");
3330 result.SetStatus(eReturnStatusFailed);
3331 return false;
3332 }
3333
3334 size_t num_matches = sc_list.GetSize();
3335 if (num_matches == 0) {
3336 result.AppendErrorWithFormat("no unwind data found that matches '%s'.",
3337 m_options.m_str.c_str());
3338 result.SetStatus(eReturnStatusFailed);
3339 return false;
3340 }
3341
3342 for (uint32_t idx = 0; idx < num_matches; idx++) {
3343 SymbolContext sc;
3344 sc_list.GetContextAtIndex(idx, sc);
3345 if (sc.symbol == nullptr && sc.function == nullptr)
3346 continue;
3347 if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr)
3348 continue;
3349 AddressRange range;
3350 if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
3351 false, range))
3352 continue;
3353 if (!range.GetBaseAddress().IsValid())
3354 continue;
3355 ConstString funcname(sc.GetFunctionName());
3356 if (funcname.IsEmpty())
3357 continue;
3358 addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target);
3359 if (abi)
3360 start_addr = abi->FixCodeAddress(start_addr);
3361
3362 FuncUnwindersSP func_unwinders_sp(
3363 sc.module_sp->GetObjectFile()
3364 ->GetUnwindTable()
3365 .GetUncachedFuncUnwindersContainingAddress(start_addr, sc));
3366 if (!func_unwinders_sp)
3367 continue;
3368
3369 result.GetOutputStream().Printf(
3370 "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64"l" "x" ")\n\n",
3371 sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(),
3372 funcname.AsCString(), start_addr);
3373
3374 UnwindPlanSP non_callsite_unwind_plan =
3375 func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread, -1);
3376 if (non_callsite_unwind_plan) {
3377 result.GetOutputStream().Printf(
3378 "Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n",
3379 non_callsite_unwind_plan->GetSourceName().AsCString());
3380 }
3381 UnwindPlanSP callsite_unwind_plan =
3382 func_unwinders_sp->GetUnwindPlanAtCallSite(*target, -1);
3383 if (callsite_unwind_plan) {
3384 result.GetOutputStream().Printf(
3385 "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n",
3386 callsite_unwind_plan->GetSourceName().AsCString());
3387 }
3388 UnwindPlanSP fast_unwind_plan =
3389 func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread);
3390 if (fast_unwind_plan) {
3391 result.GetOutputStream().Printf(
3392 "Fast UnwindPlan is '%s'\n",
3393 fast_unwind_plan->GetSourceName().AsCString());
3394 }
3395
3396 result.GetOutputStream().Printf("\n");
3397
3398 UnwindPlanSP assembly_sp =
3399 func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread, 0);
3400 if (assembly_sp) {
3401 result.GetOutputStream().Printf(
3402 "Assembly language inspection UnwindPlan:\n");
3403 assembly_sp->Dump(result.GetOutputStream(), thread.get(),
3404 LLDB_INVALID_ADDRESS(18446744073709551615UL));
3405 result.GetOutputStream().Printf("\n");
3406 }
3407
3408 UnwindPlanSP ehframe_sp =
3409 func_unwinders_sp->GetEHFrameUnwindPlan(*target, 0);
3410 if (ehframe_sp) {
3411 result.GetOutputStream().Printf("eh_frame UnwindPlan:\n");
3412 ehframe_sp->Dump(result.GetOutputStream(), thread.get(),
3413 LLDB_INVALID_ADDRESS(18446744073709551615UL));
3414 result.GetOutputStream().Printf("\n");
3415 }
3416
3417 UnwindPlanSP ehframe_augmented_sp =
3418 func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread, 0);
3419 if (ehframe_augmented_sp) {
3420 result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n");
3421 ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
3422 LLDB_INVALID_ADDRESS(18446744073709551615UL));
3423 result.GetOutputStream().Printf("\n");
3424 }
3425
3426 if (UnwindPlanSP plan_sp =
3427 func_unwinders_sp->GetDebugFrameUnwindPlan(*target, 0)) {
3428 result.GetOutputStream().Printf("debug_frame UnwindPlan:\n");
3429 plan_sp->Dump(result.GetOutputStream(), thread.get(),
3430 LLDB_INVALID_ADDRESS(18446744073709551615UL));
3431 result.GetOutputStream().Printf("\n");
3432 }
3433
3434 if (UnwindPlanSP plan_sp =
3435 func_unwinders_sp->GetDebugFrameAugmentedUnwindPlan(*target,
3436 *thread, 0)) {
3437 result.GetOutputStream().Printf("debug_frame augmented UnwindPlan:\n");
3438 plan_sp->Dump(result.GetOutputStream(), thread.get(),
3439 LLDB_INVALID_ADDRESS(18446744073709551615UL));
3440 result.GetOutputStream().Printf("\n");
3441 }
3442
3443 UnwindPlanSP arm_unwind_sp =
3444 func_unwinders_sp->GetArmUnwindUnwindPlan(*target, 0);
3445 if (arm_unwind_sp) {
3446 result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n");
3447 arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3448 LLDB_INVALID_ADDRESS(18446744073709551615UL));
3449 result.GetOutputStream().Printf("\n");
3450 }
3451
3452 UnwindPlanSP compact_unwind_sp =
3453 func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0);
3454 if (compact_unwind_sp) {
3455 result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n");
3456 compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3457 LLDB_INVALID_ADDRESS(18446744073709551615UL));
3458 result.GetOutputStream().Printf("\n");
3459 }
3460
3461 if (fast_unwind_plan) {
3462 result.GetOutputStream().Printf("Fast UnwindPlan:\n");
3463 fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(),
3464 LLDB_INVALID_ADDRESS(18446744073709551615UL));
3465 result.GetOutputStream().Printf("\n");
3466 }
3467
3468 ABISP abi_sp = process->GetABI();
3469 if (abi_sp) {
3470 UnwindPlan arch_default(lldb::eRegisterKindGeneric);
3471 if (abi_sp->CreateDefaultUnwindPlan(arch_default)) {
3472 result.GetOutputStream().Printf("Arch default UnwindPlan:\n");
3473 arch_default.Dump(result.GetOutputStream(), thread.get(),
3474 LLDB_INVALID_ADDRESS(18446744073709551615UL));
3475 result.GetOutputStream().Printf("\n");
3476 }
3477
3478 UnwindPlan arch_entry(lldb::eRegisterKindGeneric);
3479 if (abi_sp->CreateFunctionEntryUnwindPlan(arch_entry)) {
3480 result.GetOutputStream().Printf(
3481 "Arch default at entry point UnwindPlan:\n");
3482 arch_entry.Dump(result.GetOutputStream(), thread.get(),
3483 LLDB_INVALID_ADDRESS(18446744073709551615UL));
3484 result.GetOutputStream().Printf("\n");
3485 }
3486 }
3487
3488 result.GetOutputStream().Printf("\n");
3489 }
3490 return result.Succeeded();
3491 }
3492
3493 CommandOptions m_options;
3494};
3495
3496//----------------------------------------------------------------------
3497// Lookup information in images
3498//----------------------------------------------------------------------
3499
3500static OptionDefinition g_target_modules_lookup_options[] = {
3501 // clang-format off
3502 { LLDB_OPT_SET_1(1U << 0), true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules." },
3503 { LLDB_OPT_SET_1(1U << 0), false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "When looking up an address subtract <offset> from any addresses before doing the lookup." },
3504 /* FIXME: re-enable regex for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */
3505 { LLDB_OPT_SET_2(1U << 1) | LLDB_OPT_SET_4(1U << 3) | LLDB_OPT_SET_5(1U << 4), false, "regex", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "The <name> argument for name lookups are regular expressions." },
3506 { LLDB_OPT_SET_2(1U << 1), true, "symbol", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSymbol, "Lookup a symbol by name in the symbol tables in one or more target modules." },
3507 { LLDB_OPT_SET_3(1U << 2), true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more target modules." },
3508 { LLDB_OPT_SET_3(1U << 2), false, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)." },
3509 { LLDB_OPT_SET_FROM_TO(3,5)(((1U << (5)) - 1) ^ (((1U << (3)) - 1) >> 1
))
, false, "no-inlines", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Ignore inline entries (must be used in conjunction with --file or --function)." },
3510 { LLDB_OPT_SET_4(1U << 3), true, "function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFunctionName, "Lookup a function by name in the debug symbols in one or more target modules." },
3511 { LLDB_OPT_SET_5(1U << 4), true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFunctionOrSymbol, "Lookup a function or symbol by name in one or more target modules." },
3512 { LLDB_OPT_SET_6(1U << 5), true, "type", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Lookup a type by name in the debug symbols in one or more target modules." },
3513 { LLDB_OPT_SET_ALL0xFFFFFFFFU, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose lookup information." },
3514 { LLDB_OPT_SET_ALL0xFFFFFFFFU, false, "all", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Print all matches, not just the best match, if a best match is available." },
3515 // clang-format on
3516};
3517
3518class CommandObjectTargetModulesLookup : public CommandObjectParsed {
3519public:
3520 enum {
3521 eLookupTypeInvalid = -1,
3522 eLookupTypeAddress = 0,
3523 eLookupTypeSymbol,
3524 eLookupTypeFileLine, // Line is optional
3525 eLookupTypeFunction,
3526 eLookupTypeFunctionOrSymbol,
3527 eLookupTypeType,
3528 kNumLookupTypes
3529 };
3530
3531 class CommandOptions : public Options {
3532 public:
3533 CommandOptions() : Options() { OptionParsingStarting(nullptr); }
3534
3535 ~CommandOptions() override = default;
3536
3537 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3538 ExecutionContext *execution_context) override {
3539 Status error;
3540
3541 const int short_option = m_getopt_table[option_idx].val;
3542
3543 switch (short_option) {
3544 case 'a': {
3545 m_type = eLookupTypeAddress;
3546 m_addr = Args::StringToAddress(execution_context, option_arg,
3547 LLDB_INVALID_ADDRESS(18446744073709551615UL), &error);
3548 } break;
3549
3550 case 'o':
3551 if (option_arg.getAsInteger(0, m_offset))
3552 error.SetErrorStringWithFormat("invalid offset string '%s'",
3553 option_arg.str().c_str());
3554 break;
3555
3556 case 's':
3557 m_str = option_arg;
3558 m_type = eLookupTypeSymbol;
3559 break;
3560
3561 case 'f':
3562 m_file.SetFile(option_arg, false);
3563 m_type = eLookupTypeFileLine;
3564 break;
3565
3566 case 'i':
3567 m_include_inlines = false;
3568 break;
3569
3570 case 'l':
3571 if (option_arg.getAsInteger(0, m_line_number))
3572 error.SetErrorStringWithFormat("invalid line number string '%s'",
3573 option_arg.str().c_str());
3574 else if (m_line_number == 0)
3575 error.SetErrorString("zero is an invalid line number");
3576 m_type = eLookupTypeFileLine;
3577 break;
3578
3579 case 'F':
3580 m_str = option_arg;
3581 m_type = eLookupTypeFunction;
3582 break;
3583
3584 case 'n':
3585 m_str = option_arg;
3586 m_type = eLookupTypeFunctionOrSymbol;
3587 break;
3588
3589 case 't':
3590 m_str = option_arg;
3591 m_type = eLookupTypeType;
3592 break;
3593
3594 case 'v':
3595 m_verbose = 1;
3596 break;
3597
3598 case 'A':
3599 m_print_all = true;
3600 break;
3601
3602 case 'r':
3603 m_use_regex = true;
3604 break;
3605 }
3606
3607 return error;
3608 }
3609
3610 void OptionParsingStarting(ExecutionContext *execution_context) override {
3611 m_type = eLookupTypeInvalid;
3612 m_str.clear();
3613 m_file.Clear();
3614 m_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL);
3615 m_offset = 0;
3616 m_line_number = 0;
3617 m_use_regex = false;
3618 m_include_inlines = true;
3619 m_verbose = false;
3620 m_print_all = false;
3621 }
3622
3623 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3624 return llvm::makeArrayRef(g_target_modules_lookup_options);
3625 }
3626
3627 int m_type; // Should be a eLookupTypeXXX enum after parsing options
3628 std::string m_str; // Holds name lookup
3629 FileSpec m_file; // Files for file lookups
3630 lldb::addr_t m_addr; // Holds the address to lookup
3631 lldb::addr_t
3632 m_offset; // Subtract this offset from m_addr before doing lookups.
3633 uint32_t m_line_number; // Line number for file+line lookups
3634 bool m_use_regex; // Name lookups in m_str are regular expressions.
3635 bool m_include_inlines; // Check for inline entries when looking up by
3636 // file/line.
3637 bool m_verbose; // Enable verbose lookup info
3638 bool m_print_all; // Print all matches, even in cases where there's a best
3639 // match.
3640 };
3641
3642 CommandObjectTargetModulesLookup(CommandInterpreter &interpreter)
3643 : CommandObjectParsed(interpreter, "target modules lookup",
3644 "Look up information within executable and "
3645 "dependent shared library images.",
3646 nullptr, eCommandRequiresTarget),
3647 m_options() {
3648 CommandArgumentEntry arg;
3649 CommandArgumentData file_arg;
3650
3651 // Define the first (and only) variant of this arg.
3652 file_arg.arg_type = eArgTypeFilename;
3653 file_arg.arg_repetition = eArgRepeatStar;
3654
3655 // There is only one variant this argument could be; put it into the
3656 // argument entry.
3657 arg.push_back(file_arg);
3658
3659 // Push the data for the first argument into the m_arguments vector.
3660 m_arguments.push_back(arg);
3661 }
3662
3663 ~CommandObjectTargetModulesLookup() override = default;
3664
3665 Options *GetOptions() override { return &m_options; }
3666
3667 bool LookupHere(CommandInterpreter &interpreter, CommandReturnObject &result,
3668 bool &syntax_error) {
3669 switch (m_options.m_type) {
3670 case eLookupTypeAddress:
3671 case eLookupTypeFileLine:
3672 case eLookupTypeFunction:
3673 case eLookupTypeFunctionOrSymbol:
3674 case eLookupTypeSymbol:
3675 default:
3676 return false;
3677 case eLookupTypeType:
3678 break;
3679 }
3680
3681 StackFrameSP frame = m_exe_ctx.GetFrameSP();
3682
3683 if (!frame)
3684 return false;
3685
3686 const SymbolContext &sym_ctx(frame->GetSymbolContext(eSymbolContextModule));
3687
3688 if (!sym_ctx.module_sp)
3689 return false;
3690
3691 switch (m_options.m_type) {
3692 default:
3693 return false;
3694 case eLookupTypeType:
3695 if (!m_options.m_str.empty()) {
3696 if (LookupTypeHere(m_interpreter, result.GetOutputStream(), sym_ctx,
3697 m_options.m_str.c_str(), m_options.m_use_regex)) {
3698 result.SetStatus(eReturnStatusSuccessFinishResult);
3699 return true;
3700 }
3701 }
3702 break;
3703 }
3704
3705 return true;
3706 }
3707
3708 bool LookupInModule(CommandInterpreter &interpreter, Module *module,
3709 CommandReturnObject &result, bool &syntax_error) {
3710 switch (m_options.m_type) {
3711 case eLookupTypeAddress:
3712 if (m_options.m_addr != LLDB_INVALID_ADDRESS(18446744073709551615UL)) {
3713 if (LookupAddressInModule(
3714 m_interpreter, result.GetOutputStream(), module,
3715 eSymbolContextEverything |
3716 (m_options.m_verbose
3717 ? static_cast<int>(eSymbolContextVariable)
3718 : 0),
3719 m_options.m_addr, m_options.m_offset, m_options.m_verbose)) {
3720 result.SetStatus(eReturnStatusSuccessFinishResult);
3721 return true;
3722 }
3723 }
3724 break;
3725
3726 case eLookupTypeSymbol:
3727 if (!m_options.m_str.empty()) {
3728 if (LookupSymbolInModule(m_interpreter, result.GetOutputStream(),
3729 module, m_options.m_str.c_str(),
3730 m_options.m_use_regex, m_options.m_verbose)) {
3731 result.SetStatus(eReturnStatusSuccessFinishResult);
3732 return true;
3733 }
3734 }
3735 break;
3736
3737 case eLookupTypeFileLine:
3738 if (m_options.m_file) {
3739 if (LookupFileAndLineInModule(
3740 m_interpreter, result.GetOutputStream(), module,
3741 m_options.m_file, m_options.m_line_number,
3742 m_options.m_include_inlines, m_options.m_verbose)) {
3743 result.SetStatus(eReturnStatusSuccessFinishResult);
3744 return true;
3745 }
3746 }
3747 break;
3748
3749 case eLookupTypeFunctionOrSymbol:
3750 case eLookupTypeFunction:
3751 if (!m_options.m_str.empty()) {
3752 if (LookupFunctionInModule(
3753 m_interpreter, result.GetOutputStream(), module,
3754 m_options.m_str.c_str(), m_options.m_use_regex,
3755 m_options.m_include_inlines,
3756 m_options.m_type ==
3757 eLookupTypeFunctionOrSymbol, // include symbols
3758 m_options.m_verbose)) {
3759 result.SetStatus(eReturnStatusSuccessFinishResult);
3760 return true;
3761 }
3762 }
3763 break;
3764
3765 case eLookupTypeType:
3766 if (!m_options.m_str.empty()) {
3767 if (LookupTypeInModule(m_interpreter, result.GetOutputStream(), module,
3768 m_options.m_str.c_str(),
3769 m_options.m_use_regex)) {
3770 result.SetStatus(eReturnStatusSuccessFinishResult);
3771 return true;
3772 }
3773 }
3774 break;
3775
3776 default:
3777 m_options.GenerateOptionUsage(
3778 result.GetErrorStream(), this,
3779 GetCommandInterpreter().GetDebugger().GetTerminalWidth());
3780 syntax_error = true;
3781 break;
3782 }
3783
3784 result.SetStatus(eReturnStatusFailed);
3785 return false;
3786 }
3787
3788protected:
3789 bool DoExecute(Args &command, CommandReturnObject &result) override {
3790 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
3791 if (target == nullptr) {
3792 result.AppendError("invalid target, create a debug target using the "
3793 "'target create' command");
3794 result.SetStatus(eReturnStatusFailed);
3795 return false;
3796 } else {
3797 bool syntax_error = false;
3798 uint32_t i;
3799 uint32_t num_successful_lookups = 0;
3800 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
3801 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
3802 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
3803 // Dump all sections for all modules images
3804
3805 if (command.GetArgumentCount() == 0) {
3806 ModuleSP current_module;
3807
3808 // Where it is possible to look in the current symbol context
3809 // first, try that. If this search was successful and --all
3810 // was not passed, don't print anything else.
3811 if (LookupHere(m_interpreter, result, syntax_error)) {
3812 result.GetOutputStream().EOL();
3813 num_successful_lookups++;
3814 if (!m_options.m_print_all) {
3815 result.SetStatus(eReturnStatusSuccessFinishResult);
3816 return result.Succeeded();
3817 }
3818 }
3819
3820 // Dump all sections for all other modules
3821
3822 const ModuleList &target_modules = target->GetImages();
3823 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
3824 const size_t num_modules = target_modules.GetSize();
3825 if (num_modules > 0) {
3826 for (i = 0; i < num_modules && !syntax_error; ++i) {
3827 Module *module_pointer =
3828 target_modules.GetModulePointerAtIndexUnlocked(i);
3829
3830 if (module_pointer != current_module.get() &&
3831 LookupInModule(
3832 m_interpreter,
3833 target_modules.GetModulePointerAtIndexUnlocked(i), result,
3834 syntax_error)) {
3835 result.GetOutputStream().EOL();
3836 num_successful_lookups++;
3837 }
3838 }
3839 } else {
3840 result.AppendError("the target has no associated executable images");
3841 result.SetStatus(eReturnStatusFailed);
3842 return false;
3843 }
3844 } else {
3845 // Dump specified images (by basename or fullpath)
3846 const char *arg_cstr;
3847 for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr &&
3848 !syntax_error;
3849 ++i) {
3850 ModuleList module_list;
3851 const size_t num_matches =
3852 FindModulesByName(target, arg_cstr, module_list, false);
3853 if (num_matches > 0) {
3854 for (size_t j = 0; j < num_matches; ++j) {
3855 Module *module = module_list.GetModulePointerAtIndex(j);
3856 if (module) {
3857 if (LookupInModule(m_interpreter, module, result,
3858 syntax_error)) {
3859 result.GetOutputStream().EOL();
3860 num_successful_lookups++;
3861 }
3862 }
3863 }
3864 } else
3865 result.AppendWarningWithFormat(
3866 "Unable to find an image that matches '%s'.\n", arg_cstr);
3867 }
3868 }
3869
3870 if (num_successful_lookups > 0)
3871 result.SetStatus(eReturnStatusSuccessFinishResult);
3872 else
3873 result.SetStatus(eReturnStatusFailed);
3874 }
3875 return result.Succeeded();
3876 }
3877
3878 CommandOptions m_options;
3879};
3880
3881#pragma mark CommandObjectMultiwordImageSearchPaths
3882
3883//-------------------------------------------------------------------------
3884// CommandObjectMultiwordImageSearchPaths
3885//-------------------------------------------------------------------------
3886
3887class CommandObjectTargetModulesImageSearchPaths
3888 : public CommandObjectMultiword {
3889public:
3890 CommandObjectTargetModulesImageSearchPaths(CommandInterpreter &interpreter)
3891 : CommandObjectMultiword(
3892 interpreter, "target modules search-paths",
3893 "Commands for managing module search paths for a target.",
3894 "target modules search-paths <subcommand> [<subcommand-options>]") {
3895 LoadSubCommand(
3896 "add", CommandObjectSP(
3897 new CommandObjectTargetModulesSearchPathsAdd(interpreter)));
3898 LoadSubCommand(
3899 "clear", CommandObjectSP(new CommandObjectTargetModulesSearchPathsClear(
3900 interpreter)));
3901 LoadSubCommand(
3902 "insert",
3903 CommandObjectSP(
3904 new CommandObjectTargetModulesSearchPathsInsert(interpreter)));
3905 LoadSubCommand(
3906 "list", CommandObjectSP(new CommandObjectTargetModulesSearchPathsList(
3907 interpreter)));
3908 LoadSubCommand(
3909 "query", CommandObjectSP(new CommandObjectTargetModulesSearchPathsQuery(
3910 interpreter)));
3911 }
3912
3913 ~CommandObjectTargetModulesImageSearchPaths() override = default;
3914};
3915
3916#pragma mark CommandObjectTargetModules
3917
3918//-------------------------------------------------------------------------
3919// CommandObjectTargetModules
3920//-------------------------------------------------------------------------
3921
3922class CommandObjectTargetModules : public CommandObjectMultiword {
3923public:
3924 //------------------------------------------------------------------
3925 // Constructors and Destructors
3926 //------------------------------------------------------------------
3927 CommandObjectTargetModules(CommandInterpreter &interpreter)
3928 : CommandObjectMultiword(interpreter, "target modules",
3929 "Commands for accessing information for one or "
3930 "more target modules.",
3931 "target modules <sub-command> ...") {
3932 LoadSubCommand(
3933 "add", CommandObjectSP(new CommandObjectTargetModulesAdd(interpreter)));
3934 LoadSubCommand("load", CommandObjectSP(new CommandObjectTargetModulesLoad(
3935 interpreter)));
3936 LoadSubCommand("dump", CommandObjectSP(new CommandObjectTargetModulesDump(
3937 interpreter)));
3938 LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetModulesList(
3939 interpreter)));
3940 LoadSubCommand(
3941 "lookup",
3942 CommandObjectSP(new CommandObjectTargetModulesLookup(interpreter)));
3943 LoadSubCommand(
3944 "search-paths",
3945 CommandObjectSP(
3946 new CommandObjectTargetModulesImageSearchPaths(interpreter)));
3947 LoadSubCommand(
3948 "show-unwind",
3949 CommandObjectSP(new CommandObjectTargetModulesShowUnwind(interpreter)));
3950 }
3951
3952 ~CommandObjectTargetModules() override = default;
3953
3954private:
3955 //------------------------------------------------------------------
3956 // For CommandObjectTargetModules only
3957 //------------------------------------------------------------------
3958 DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetModules)CommandObjectTargetModules(const CommandObjectTargetModules &
) = delete; const CommandObjectTargetModules &operator=(const
CommandObjectTargetModules &) = delete
;
3959};
3960
3961class CommandObjectTargetSymbolsAdd : public CommandObjectParsed {
3962public:
3963 CommandObjectTargetSymbolsAdd(CommandInterpreter &interpreter)
3964 : CommandObjectParsed(
3965 interpreter, "target symbols add",
3966 "Add a debug symbol file to one of the target's current modules by "
3967 "specifying a path to a debug symbols file, or using the options "
3968 "to specify a module to download symbols for.",
3969 "target symbols add <cmd-options> [<symfile>]",
3970 eCommandRequiresTarget),
3971 m_option_group(),
3972 m_file_option(
3973 LLDB_OPT_SET_1(1U << 0), false, "shlib", 's',
3974 CommandCompletions::eModuleCompletion, eArgTypeShlibName,
3975 "Fullpath or basename for module to find debug symbols for."),
3976 m_current_frame_option(
3977 LLDB_OPT_SET_2(1U << 1), false, "frame", 'F',
3978 "Locate the debug symbols the currently selected frame.", false,
3979 true)
3980
3981 {
3982 m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL0xFFFFFFFFU,
3983 LLDB_OPT_SET_1(1U << 0));
3984 m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL0xFFFFFFFFU, LLDB_OPT_SET_1(1U << 0));
3985 m_option_group.Append(&m_current_frame_option, LLDB_OPT_SET_2(1U << 1),
3986 LLDB_OPT_SET_2(1U << 1));
3987 m_option_group.Finalize();
3988 }
3989
3990 ~CommandObjectTargetSymbolsAdd() override = default;
3991
3992 int HandleArgumentCompletion(Args &input, int &cursor_index,
3993 int &cursor_char_position,
3994 OptionElementVector &opt_element_vector,
3995 int match_start_point, int max_return_elements,
3996 bool &word_complete,
3997 StringList &matches) override {
3998 std::string completion_str(input.GetArgumentAtIndex(cursor_index));
3999 completion_str.erase(cursor_char_position);
4000
4001 CommandCompletions::InvokeCommonCompletionCallbacks(
4002 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
4003 completion_str.c_str(), match_start_point, max_return_elements, nullptr,
4004 word_complete, matches);
4005 return matches.GetSize();
4006 }
4007
4008 Options *GetOptions() override { return &m_option_group; }
4009
4010protected:
4011 bool AddModuleSymbols(Target *target, ModuleSpec &module_spec, bool &flush,
4012 CommandReturnObject &result) {
4013 const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec();
4014 if (symbol_fspec) {
4015 char symfile_path[PATH_MAX4096];
4016 symbol_fspec.GetPath(symfile_path, sizeof(symfile_path));
4017
4018 if (!module_spec.GetUUID().IsValid()) {
4019 if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
4020 module_spec.GetFileSpec().GetFilename() = symbol_fspec.GetFilename();
4021 }
4022 // We now have a module that represents a symbol file
4023 // that can be used for a module that might exist in the
4024 // current target, so we need to find that module in the
4025 // target
4026 ModuleList matching_module_list;
4027
4028 size_t num_matches = 0;
4029 // First extract all module specs from the symbol file
4030 lldb_private::ModuleSpecList symfile_module_specs;
4031 if (ObjectFile::GetModuleSpecifications(module_spec.GetSymbolFileSpec(),
4032 0, 0, symfile_module_specs)) {
4033 // Now extract the module spec that matches the target architecture
4034 ModuleSpec target_arch_module_spec;
4035 ModuleSpec symfile_module_spec;
4036 target_arch_module_spec.GetArchitecture() = target->GetArchitecture();
4037 if (symfile_module_specs.FindMatchingModuleSpec(target_arch_module_spec,
4038 symfile_module_spec)) {
4039 // See if it has a UUID?
4040 if (symfile_module_spec.GetUUID().IsValid()) {
4041 // It has a UUID, look for this UUID in the target modules
4042 ModuleSpec symfile_uuid_module_spec;
4043 symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();
4044 num_matches = target->GetImages().FindModules(
4045 symfile_uuid_module_spec, matching_module_list);
4046 }
4047 }
4048
4049 if (num_matches == 0) {
4050 // No matches yet, iterate through the module specs to find a UUID
4051 // value that
4052 // we can match up to an image in our target
4053 const size_t num_symfile_module_specs =
4054 symfile_module_specs.GetSize();
4055 for (size_t i = 0; i < num_symfile_module_specs && num_matches == 0;
4056 ++i) {
4057 if (symfile_module_specs.GetModuleSpecAtIndex(
4058 i, symfile_module_spec)) {
4059 if (symfile_module_spec.GetUUID().IsValid()) {
4060 // It has a UUID, look for this UUID in the target modules
4061 ModuleSpec symfile_uuid_module_spec;
4062 symfile_uuid_module_spec.GetUUID() =
4063 symfile_module_spec.GetUUID();
4064 num_matches = target->GetImages().FindModules(
4065 symfile_uuid_module_spec, matching_module_list);
4066 }
4067 }
4068 }
4069 }
4070 }
4071
4072 // Just try to match up the file by basename if we have no matches at this
4073 // point
4074 if (num_matches == 0)
4075 num_matches =
4076 target->GetImages().FindModules(module_spec, matching_module_list);
4077
4078 while (num_matches == 0) {
4079 ConstString filename_no_extension(
4080 module_spec.GetFileSpec().GetFileNameStrippingExtension());
4081 // Empty string returned, lets bail
4082 if (!filename_no_extension)
4083 break;
4084
4085 // Check if there was no extension to strip and the basename is the same
4086 if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
4087 break;
4088
4089 // Replace basename with one less extension
4090 module_spec.GetFileSpec().GetFilename() = filename_no_extension;
4091
4092 num_matches =
4093 target->GetImages().FindModules(module_spec, matching_module_list);
4094 }
4095
4096 if (num_matches > 1) {
4097 result.AppendErrorWithFormat("multiple modules match symbol file '%s', "
4098 "use the --uuid option to resolve the "
4099 "ambiguity.\n",
4100 symfile_path);
4101 } else if (num_matches == 1) {
4102 ModuleSP module_sp(matching_module_list.GetModuleAtIndex(0));
4103
4104 // The module has not yet created its symbol vendor, we can just
4105 // give the existing target module the symfile path to use for
4106 // when it decides to create it!
4107 module_sp->SetSymbolFileFileSpec(symbol_fspec);
4108
4109 SymbolVendor *symbol_vendor =
4110 module_sp->GetSymbolVendor(true, &result.GetErrorStream());
4111 if (symbol_vendor) {
4112 SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
4113
4114 if (symbol_file) {
4115 ObjectFile *object_file = symbol_file->GetObjectFile();
4116
4117 if (object_file && object_file->GetFileSpec() == symbol_fspec) {
4118 // Provide feedback that the symfile has been successfully added.
4119 const FileSpec &module_fs = module_sp->GetFileSpec();
4120 result.AppendMessageWithFormat(
4121 "symbol file '%s' has been added to '%s'\n", symfile_path,
4122 module_fs.GetPath().c_str());
4123
4124 // Let clients know something changed in the module
4125 // if it is currently loaded
4126 ModuleList module_list;
4127 module_list.Append(module_sp);
4128 target->SymbolsDidLoad(module_list);
4129
4130 // Make sure we load any scripting resources that may be embedded
4131 // in the debug info files in case the platform supports that.
4132 Status error;
4133 StreamString feedback_stream;
4134 module_sp->LoadScriptingResourceInTarget(target, error,
4135 &feedback_stream);
4136 if (error.Fail() && error.AsCString())
4137 result.AppendWarningWithFormat(
4138 "unable to load scripting data for module %s - error "
4139 "reported was %s",
4140 module_sp->GetFileSpec()
4141 .GetFileNameStrippingExtension()
4142 .GetCString(),
4143 error.AsCString());
4144 else if (feedback_stream.GetSize())
4145 result.AppendWarningWithFormat("%s", feedback_stream.GetData());
4146
4147 flush = true;
4148 result.SetStatus(eReturnStatusSuccessFinishResult);
4149 return true;
4150 }
4151 }
4152 }
4153 // Clear the symbol file spec if anything went wrong
4154 module_sp->SetSymbolFileFileSpec(FileSpec());
4155 }
4156
4157 namespace fs = llvm::sys::fs;
4158 if (module_spec.GetUUID().IsValid()) {
4159 StreamString ss_symfile_uuid;
4160 module_spec.GetUUID().Dump(&ss_symfile_uuid);
4161 result.AppendErrorWithFormat(
4162 "symbol file '%s' (%s) does not match any existing module%s\n",
4163 symfile_path, ss_symfile_uuid.GetData(),
4164 !fs::is_regular_file(symbol_fspec.GetPath())
4165 ? "\n please specify the full path to the symbol file"
4166 : "");
4167 } else {
4168 result.AppendErrorWithFormat(
4169 "symbol file '%s' does not match any existing module%s\n",
4170 symfile_path,
4171 !fs::is_regular_file(symbol_fspec.GetPath())
4172 ? "\n please specify the full path to the symbol file"
4173 : "");
4174 }
4175 } else {
4176 result.AppendError(
4177 "one or more executable image paths must be specified");
4178 }
4179 result.SetStatus(eReturnStatusFailed);
4180 return false;
4181 }
4182
4183 bool DoExecute(Args &args, CommandReturnObject &result) override {
4184 Target *target = m_exe_ctx.GetTargetPtr();
4185 result.SetStatus(eReturnStatusFailed);
4186 bool flush = false;
4187 ModuleSpec module_spec;
4188 const bool uuid_option_set =
4189 m_uuid_option_group.GetOptionValue().OptionWasSet();
4190 const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
4191 const bool frame_option_set =
4192 m_current_frame_option.GetOptionValue().OptionWasSet();
4193 const size_t argc = args.GetArgumentCount();
4194
4195 if (argc == 0) {
4196 if (uuid_option_set || file_option_set || frame_option_set) {
4197 bool success = false;
4198 bool error_set = false;
4199 if (frame_option_set) {
4200 Process *process = m_exe_ctx.GetProcessPtr();
4201 if (process) {
4202 const StateType process_state = process->GetState();
4203 if (StateIsStoppedState(process_state, true)) {
4204 StackFrame *frame = m_exe_ctx.GetFramePtr();
4205 if (frame) {
4206 ModuleSP frame_module_sp(
4207 frame->GetSymbolContext(eSymbolContextModule).module_sp);
4208 if (frame_module_sp) {
4209 if (frame_module_sp->GetPlatformFileSpec().Exists()) {
4210 module_spec.GetArchitecture() =
4211 frame_module_sp->GetArchitecture();
4212 module_spec.GetFileSpec() =
4213 frame_module_sp->GetPlatformFileSpec();
4214 }
4215 module_spec.GetUUID() = frame_module_sp->GetUUID();
4216 success = module_spec.GetUUID().IsValid() ||
4217 module_spec.GetFileSpec();
4218 } else {
4219 result.AppendError("frame has no module");
4220 error_set = true;
4221 }
4222 } else {
4223 result.AppendError("invalid current frame");
4224 error_set = true;
4225 }
4226 } else {
4227 result.AppendErrorWithFormat("process is not stopped: %s",
4228 StateAsCString(process_state));
4229 error_set = true;
4230 }
4231 } else {
4232 result.AppendError(
4233 "a process must exist in order to use the --frame option");
4234 error_set = true;
4235 }
4236 } else {
4237 if (uuid_option_set) {
4238 module_spec.GetUUID() =
4239 m_uuid_option_group.GetOptionValue().GetCurrentValue();
4240 success |= module_spec.GetUUID().IsValid();
4241 } else if (file_option_set) {
4242 module_spec.GetFileSpec() =
4243 m_file_option.GetOptionValue().GetCurrentValue();
4244 ModuleSP module_sp(
4245 target->GetImages().FindFirstModule(module_spec));
4246 if (module_sp) {
4247 module_spec.GetFileSpec() = module_sp->GetFileSpec();
4248 module_spec.GetPlatformFileSpec() =
4249 module_sp->GetPlatformFileSpec();
4250 module_spec.GetUUID() = module_sp->GetUUID();
4251 module_spec.GetArchitecture() = module_sp->GetArchitecture();
4252 } else {
4253 module_spec.GetArchitecture() = target->GetArchitecture();
4254 }
4255 success |= module_spec.GetUUID().IsValid() ||
4256 module_spec.GetFileSpec().Exists();
4257 }
4258 }
4259
4260 if (success) {
4261 if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
4262 if (module_spec.GetSymbolFileSpec())
4263 success = AddModuleSymbols(target, module_spec, flush, result);
4264 }
4265 }
4266
4267 if (!success && !error_set) {
4268 StreamString error_strm;
4269 if (uuid_option_set) {
4270 error_strm.PutCString("unable to find debug symbols for UUID ");
4271 module_spec.GetUUID().Dump(&error_strm);
4272 } else if (file_option_set) {
4273 error_strm.PutCString(
4274 "unable to find debug symbols for the executable file ");
4275 error_strm << module_spec.GetFileSpec();
4276 } else if (frame_option_set) {
4277 error_strm.PutCString(
4278 "unable to find debug symbols for the current frame");
4279 }
4280 result.AppendError(error_strm.GetString());
4281 }
4282 } else {
4283 result.AppendError("one or more symbol file paths must be specified, "
4284 "or options must be specified");
4285 }
4286 } else {
4287 if (uuid_option_set) {
4288 result.AppendError("specify either one or more paths to symbol files "
4289 "or use the --uuid option without arguments");
4290 } else if (frame_option_set) {
4291 result.AppendError("specify either one or more paths to symbol files "
4292 "or use the --frame option without arguments");
4293 } else if (file_option_set && argc > 1) {
4294 result.AppendError("specify at most one symbol file path when "
4295 "--shlib option is set");
4296 } else {
4297 PlatformSP platform_sp(target->GetPlatform());
4298
4299 for (auto &entry : args.entries()) {
4300 if (!entry.ref.empty()) {
4301 module_spec.GetSymbolFileSpec().SetFile(entry.ref, true);
4302 if (file_option_set) {
4303 module_spec.GetFileSpec() =
4304 m_file_option.GetOptionValue().GetCurrentValue();
4305 }
4306 if (platform_sp) {
4307 FileSpec symfile_spec;
4308 if (platform_sp
4309 ->ResolveSymbolFile(*target, module_spec, symfile_spec)
4310 .Success())
4311 module_spec.GetSymbolFileSpec() = symfile_spec;
4312 }
4313
4314 ArchSpec arch;
4315 bool symfile_exists = module_spec.GetSymbolFileSpec().Exists();
4316
4317 if (symfile_exists) {
4318 if (!AddModuleSymbols(target, module_spec, flush, result))
4319 break;
4320 } else {
4321 std::string resolved_symfile_path =
4322 module_spec.GetSymbolFileSpec().GetPath();
4323 if (resolved_symfile_path != entry.ref) {
4324 result.AppendErrorWithFormat(
4325 "invalid module path '%s' with resolved path '%s'\n",
4326 entry.c_str(), resolved_symfile_path.c_str());
4327 break;
4328 }
4329 result.AppendErrorWithFormat("invalid module path '%s'\n",
4330 entry.c_str());
4331 break;
4332 }
4333 }
4334 }
4335 }
4336 }
4337
4338 if (flush) {
4339 Process *process = m_exe_ctx.GetProcessPtr();
4340 if (process)
4341 process->Flush();
4342 }
4343 return result.Succeeded();
4344 }
4345
4346 OptionGroupOptions m_option_group;
4347 OptionGroupUUID m_uuid_option_group;
4348 OptionGroupFile m_file_option;
4349 OptionGroupBoolean m_current_frame_option;
4350};
4351
4352#pragma mark CommandObjectTargetSymbols
4353
4354//-------------------------------------------------------------------------
4355// CommandObjectTargetSymbols
4356//-------------------------------------------------------------------------
4357
4358class CommandObjectTargetSymbols : public CommandObjectMultiword {
4359public:
4360 //------------------------------------------------------------------
4361 // Constructors and Destructors
4362 //------------------------------------------------------------------
4363 CommandObjectTargetSymbols(CommandInterpreter &interpreter)
4364 : CommandObjectMultiword(
4365 interpreter, "target symbols",
4366 "Commands for adding and managing debug symbol files.",
4367 "target symbols <sub-command> ...") {
4368 LoadSubCommand(
4369 "add", CommandObjectSP(new CommandObjectTargetSymbolsAdd(interpreter)));
4370 }
4371
4372 ~CommandObjectTargetSymbols() override = default;
4373
4374private:
4375 //------------------------------------------------------------------
4376 // For CommandObjectTargetModules only
4377 //------------------------------------------------------------------
4378 DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetSymbols)CommandObjectTargetSymbols(const CommandObjectTargetSymbols &
) = delete; const CommandObjectTargetSymbols &operator=(const
CommandObjectTargetSymbols &) = delete
;
4379};
4380
4381#pragma mark CommandObjectTargetStopHookAdd
4382
4383//-------------------------------------------------------------------------
4384// CommandObjectTargetStopHookAdd
4385//-------------------------------------------------------------------------
4386
4387static OptionDefinition g_target_stop_hook_add_options[] = {
4388 // clang-format off
4389 { LLDB_OPT_SET_ALL0xFFFFFFFFU, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
4390 { LLDB_OPT_SET_ALL0xFFFFFFFFU, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the module within which the stop-hook is to be run." },
4391 { LLDB_OPT_SET_ALL0xFFFFFFFFU, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The stop hook is run only for the thread whose index matches this argument." },
4392 { LLDB_OPT_SET_ALL0xFFFFFFFFU, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The stop hook is run only for the thread whose TID matches this argument." },
4393 { LLDB_OPT_SET_ALL0xFFFFFFFFU, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The stop hook is run only for the thread whose thread name matches this argument." },
4394 { LLDB_OPT_SET_ALL0xFFFFFFFFU, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The stop hook is run only for threads in the queue whose name is given by this argument." },
4395 { LLDB_OPT_SET_1(1U << 0), false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the source file within which the stop-hook is to be run." },
4396 { LLDB_OPT_SET_1(1U << 0), false, "start-line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Set the start of the line range for which the stop-hook is to be run." },
4397 { LLDB_OPT_SET_1(1U << 0), false, "end-line", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Set the end of the line range for which the stop-hook is to be run." },
4398 { LLDB_OPT_SET_2(1U << 1), false, "classname", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeClassName, "Specify the class within which the stop-hook is to be run." },
4399 { LLDB_OPT_SET_3(1U << 2), false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the function name within which the stop hook will be run." },
4400 // clang-format on
4401};
4402
4403class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
4404 public IOHandlerDelegateMultiline {
4405public:
4406 class CommandOptions : public Options {
4407 public:
4408 CommandOptions()
4409 : Options(), m_line_start(0), m_line_end(UINT_MAX(2147483647 *2U +1U)),
4410 m_func_name_type_mask(eFunctionNameTypeAuto),
4411 m_sym_ctx_specified(false), m_thread_specified(false),
4412 m_use_one_liner(false), m_one_liner() {}
4413
4414 ~CommandOptions() override = default;
4415
4416 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4417 return llvm::makeArrayRef(g_target_stop_hook_add_options);
4418 }
4419
4420 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4421 ExecutionContext *execution_context) override {
4422 Status error;
4423 const int short_option = m_getopt_table[option_idx].val;
4424
4425 switch (short_option) {
4426 case 'c':
4427 m_class_name = option_arg;
4428 m_sym_ctx_specified = true;
4429 break;
4430
4431 case 'e':
4432 if (option_arg.getAsInteger(0, m_line_end)) {
4433 error.SetErrorStringWithFormat("invalid end line number: \"%s\"",
4434 option_arg.str().c_str());
4435 break;
4436 }
4437 m_sym_ctx_specified = true;
4438 break;
4439
4440 case 'l':
4441 if (option_arg.getAsInteger(0, m_line_start)) {
4442 error.SetErrorStringWithFormat("invalid start line number: \"%s\"",
4443 option_arg.str().c_str());
4444 break;
4445 }
4446 m_sym_ctx_specified = true;
4447 break;
4448
4449 case 'i':
4450 m_no_inlines = true;
4451 break;
4452
4453 case 'n':
4454 m_function_name = option_arg;
4455 m_func_name_type_mask |= eFunctionNameTypeAuto;
4456 m_sym_ctx_specified = true;
4457 break;
4458
4459 case 'f':
4460 m_file_name = option_arg;
4461 m_sym_ctx_specified = true;
4462 break;
4463
4464 case 's':
4465 m_module_name = option_arg;
4466 m_sym_ctx_specified = true;
4467 break;
4468
4469 case 't':
4470 if (option_arg.getAsInteger(0, m_thread_id))
4471 error.SetErrorStringWithFormat("invalid thread id string '%s'",
4472 option_arg.str().c_str());
4473 m_thread_specified = true;
4474 break;
4475
4476 case 'T':
4477 m_thread_name = option_arg;
4478 m_thread_specified = true;
4479 break;
4480
4481 case 'q':
4482 m_queue_name = option_arg;
4483 m_thread_specified = true;
4484 break;
4485
4486 case 'x':
4487 if (option_arg.getAsInteger(0, m_thread_index))
4488 error.SetErrorStringWithFormat("invalid thread index string '%s'",
4489 option_arg.str().c_str());
4490 m_thread_specified = true;
4491 break;
4492
4493 case 'o':
4494 m_use_one_liner = true;
4495 m_one_liner = option_arg;
4496 break;
4497
4498 default:
4499 error.SetErrorStringWithFormat("unrecognized option %c.", short_option);
4500 break;
4501 }
4502 return error;
4503 }
4504
4505 void OptionParsingStarting(ExecutionContext *execution_context) override {
4506 m_class_name.clear();
4507 m_function_name.clear();
4508 m_line_start = 0;
4509 m_line_end = UINT_MAX(2147483647 *2U +1U);
4510 m_file_name.clear();
4511 m_module_name.clear();
4512 m_func_name_type_mask = eFunctionNameTypeAuto;
4513 m_thread_id = LLDB_INVALID_THREAD_ID0;
4514 m_thread_index = UINT32_MAX(4294967295U);
4515 m_thread_name.clear();
4516 m_queue_name.clear();
4517
4518 m_no_inlines = false;
4519 m_sym_ctx_specified = false;
4520 m_thread_specified = false;
4521
4522 m_use_one_liner = false;
4523 m_one_liner.clear();
4524 }
4525
4526 std::string m_class_name;
4527 std::string m_function_name;
4528 uint32_t m_line_start;
4529 uint32_t m_line_end;
4530 std::string m_file_name;
4531 std::string m_module_name;
4532 uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType.
4533 lldb::tid_t m_thread_id;
4534 uint32_t m_thread_index;
4535 std::string m_thread_name;
4536 std::string m_queue_name;
4537 bool m_sym_ctx_specified;
4538 bool m_no_inlines;
4539 bool m_thread_specified;
4540 // Instance variables to hold the values for one_liner options.
4541 bool m_use_one_liner;
4542 std::string m_one_liner;
4543 };
4544
4545 CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter)
4546 : CommandObjectParsed(interpreter, "target stop-hook add",
4547 "Add a hook to be executed when the target stops.",
4548 "target stop-hook add"),
4549 IOHandlerDelegateMultiline("DONE",
4550 IOHandlerDelegate::Completion::LLDBCommand),
4551 m_options() {}
4552
4553 ~CommandObjectTargetStopHookAdd() override = default;
4554
4555 Options *GetOptions() override { return &m_options; }
4556
4557protected:
4558 void IOHandlerActivated(IOHandler &io_handler) override {
4559 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
4560 if (output_sp) {
4561 output_sp->PutCString(
4562 "Enter your stop hook command(s). Type 'DONE' to end.\n");
4563 output_sp->Flush();
4564 }
4565 }
4566
4567 void IOHandlerInputComplete(IOHandler &io_handler,
4568 std::string &line) override {
4569 if (m_stop_hook_sp) {
4570 if (line.empty()) {
4571 StreamFileSP error_sp(io_handler.GetErrorStreamFile());
4572 if (error_sp) {
4573 error_sp->Printf("error: stop hook #%" PRIu64"l" "u"
4574 " aborted, no commands.\n",
4575 m_stop_hook_sp->GetID());
4576 error_sp->Flush();
4577 }
4578 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
4579 if (target)
4580 target->RemoveStopHookByID(m_stop_hook_sp->GetID());
4581 } else {
4582 m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line);
4583 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
4584 if (output_sp) {
4585 output_sp->Printf("Stop hook #%" PRIu64"l" "u" " added.\n",
4586 m_stop_hook_sp->GetID());
4587 output_sp->Flush();
4588 }
4589 }
4590 m_stop_hook_sp.reset();
4591 }
4592 io_handler.SetIsDone(true);
4593 }
4594
4595 bool DoExecute(Args &command, CommandReturnObject &result) override {
4596 m_stop_hook_sp.reset();
4597
4598 Target *target = GetSelectedOrDummyTarget();
4599 if (target) {
4600 Target::StopHookSP new_hook_sp = target->CreateStopHook();
4601
4602 // First step, make the specifier.
4603 std::unique_ptr<SymbolContextSpecifier> specifier_ap;
4604 if (m_options.m_sym_ctx_specified) {
4605 specifier_ap.reset(new SymbolContextSpecifier(
4606 m_interpreter.GetDebugger().GetSelectedTarget()));
4607
4608 if (!m_options.m_module_name.empty()) {
4609 specifier_ap->AddSpecification(
4610 m_options.m_module_name.c_str(),
4611 SymbolContextSpecifier::eModuleSpecified);
4612 }
4613
4614 if (!m_options.m_class_name.empty()) {
4615 specifier_ap->AddSpecification(
4616 m_options.m_class_name.c_str(),
4617 SymbolContextSpecifier::eClassOrNamespaceSpecified);
4618 }
4619
4620 if (!m_options.m_file_name.empty()) {
4621 specifier_ap->AddSpecification(
4622 m_options.m_file_name.c_str(),
4623 SymbolContextSpecifier::eFileSpecified);
4624 }
4625
4626 if (m_options.m_line_start != 0) {
4627 specifier_ap->AddLineSpecification(
4628 m_options.m_line_start,
4629 SymbolContextSpecifier::eLineStartSpecified);
4630 }
4631
4632 if (m_options.m_line_end != UINT_MAX(2147483647 *2U +1U)) {
4633 specifier_ap->AddLineSpecification(
4634 m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
4635 }
4636
4637 if (!m_options.m_function_name.empty()) {
4638 specifier_ap->AddSpecification(
4639 m_options.m_function_name.c_str(),
4640 SymbolContextSpecifier::eFunctionSpecified);
4641 }
4642 }
4643
4644 if (specifier_ap)
4645 new_hook_sp->SetSpecifier(specifier_ap.release());
4646
4647 // Next see if any of the thread options have been entered:
4648
4649 if (m_options.m_thread_specified) {
4650 ThreadSpec *thread_spec = new ThreadSpec();
4651
4652 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID0) {
4653 thread_spec->SetTID(m_options.m_thread_id);
4654 }
4655
4656 if (m_options.m_thread_index != UINT32_MAX(4294967295U))
4657 thread_spec->SetIndex(m_options.m_thread_index);
4658
4659 if (!m_options.m_thread_name.empty())
4660 thread_spec->SetName(m_options.m_thread_name.c_str());
4661
4662 if (!m_options.m_queue_name.empty())
4663 thread_spec->SetQueueName(m_options.m_queue_name.c_str());
4664
4665 new_hook_sp->SetThreadSpecifier(thread_spec);
4666 }
4667 if (m_options.m_use_one_liner) {
4668 // Use one-liner.
4669 new_hook_sp->GetCommandPointer()->AppendString(
4670 m_options.m_one_liner.c_str());
4671 result.AppendMessageWithFormat("Stop hook #%" PRIu64"l" "u" " added.\n",
4672 new_hook_sp->GetID());
4673 } else {
4674 m_stop_hook_sp = new_hook_sp;
4675 m_interpreter.GetLLDBCommandsFromIOHandler(
4676 "> ", // Prompt
4677 *this, // IOHandlerDelegate
4678 true, // Run IOHandler in async mode
4679 nullptr); // Baton for the "io_handler" that will be passed back
4680 // into our IOHandlerDelegate functions
4681 }
4682 result.SetStatus(eReturnStatusSuccessFinishNoResult);
4683 } else {
4684 result.AppendError("invalid target\n");
4685 result.SetStatus(eReturnStatusFailed);
4686 }
4687
4688 return result.Succeeded();
4689 }
4690
4691private:
4692 CommandOptions m_options;
4693 Target::StopHookSP m_stop_hook_sp;
4694};
4695
4696#pragma mark CommandObjectTargetStopHookDelete
4697
4698//-------------------------------------------------------------------------
4699// CommandObjectTargetStopHookDelete
4700//-------------------------------------------------------------------------
4701
4702class CommandObjectTargetStopHookDelete : public CommandObjectParsed {
4703public:
4704 CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter)
4705 : CommandObjectParsed(interpreter, "target stop-hook delete",
4706 "Delete a stop-hook.",
4707 "target stop-hook delete [<idx>]") {}
4708
4709 ~CommandObjectTargetStopHookDelete() override = default;
4710
4711protected:
4712 bool DoExecute(Args &command, CommandReturnObject &result) override {
4713 Target *target = GetSelectedOrDummyTarget();
4714 if (target) {
4715 // FIXME: see if we can use the breakpoint id style parser?
4716 size_t num_args = command.GetArgumentCount();
4717 if (num_args == 0) {
4718 if (!m_interpreter.Confirm("Delete all stop hooks?", true)) {
4719 result.SetStatus(eReturnStatusFailed);
4720 return false;
4721 } else {
4722 target->RemoveAllStopHooks();
4723 }
4724 } else {
4725 bool success;
4726 for (size_t i = 0; i < num_args; i++) {
4727 lldb::user_id_t user_id = StringConvert::ToUInt32(
4728 command.GetArgumentAtIndex(i), 0, 0, &success);
4729 if (!success) {
4730 result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4731 command.GetArgumentAtIndex(i));
4732 result.SetStatus(eReturnStatusFailed);
4733 return false;
4734 }
4735 success = target->RemoveStopHookByID(user_id);
4736 if (!success) {
4737 result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4738 command.GetArgumentAtIndex(i));
4739 result.SetStatus(eReturnStatusFailed);
4740 return false;
4741 }
4742 }
4743 }
4744 result.SetStatus(eReturnStatusSuccessFinishNoResult);
4745 } else {
4746 result.AppendError("invalid target\n");
4747 result.SetStatus(eReturnStatusFailed);
4748 }
4749
4750 return result.Succeeded();
4751 }
4752};
4753
4754#pragma mark CommandObjectTargetStopHookEnableDisable
4755
4756//-------------------------------------------------------------------------
4757// CommandObjectTargetStopHookEnableDisable
4758//-------------------------------------------------------------------------
4759
4760class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed {
4761public:
4762 CommandObjectTargetStopHookEnableDisable(CommandInterpreter &interpreter,
4763 bool enable, const char *name,
4764 const char *help, const char *syntax)
4765 : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) {
4766 }
4767
4768 ~CommandObjectTargetStopHookEnableDisable() override = default;
4769
4770protected:
4771 bool DoExecute(Args &command, CommandReturnObject &result) override {
4772 Target *target = GetSelectedOrDummyTarget();
4773 if (target) {
4774 // FIXME: see if we can use the breakpoint id style parser?
4775 size_t num_args = command.GetArgumentCount();
4776 bool success;
4777
4778 if (num_args == 0) {
4779 target->SetAllStopHooksActiveState(m_enable);
4780 } else {
4781 for (size_t i = 0; i < num_args; i++) {
4782 lldb::user_id_t user_id = StringConvert::ToUInt32(
4783 command.GetArgumentAtIndex(i), 0, 0, &success);
4784 if (!success) {
4785 result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4786 command.GetArgumentAtIndex(i));
4787 result.SetStatus(eReturnStatusFailed);
4788 return false;
4789 }
4790 success = target->SetStopHookActiveStateByID(user_id, m_enable);
4791 if (!success) {
4792 result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4793 command.GetArgumentAtIndex(i));
4794 result.SetStatus(eReturnStatusFailed);
4795 return false;
4796 }
4797 }
4798 }
4799 result.SetStatus(eReturnStatusSuccessFinishNoResult);
4800 } else {
4801 result.AppendError("invalid target\n");
4802 result.SetStatus(eReturnStatusFailed);
4803 }
4804 return result.Succeeded();
4805 }
4806
4807private:
4808 bool m_enable;
4809};
4810
4811#pragma mark CommandObjectTargetStopHookList
4812
4813//-------------------------------------------------------------------------
4814// CommandObjectTargetStopHookList
4815//-------------------------------------------------------------------------
4816
4817class CommandObjectTargetStopHookList : public CommandObjectParsed {
4818public:
4819 CommandObjectTargetStopHookList(CommandInterpreter &interpreter)
4820 : CommandObjectParsed(interpreter, "target stop-hook list",
4821 "List all stop-hooks.",
4822 "target stop-hook list [<type>]") {}
4823
4824 ~CommandObjectTargetStopHookList() override = default;
4825
4826protected:
4827 bool DoExecute(Args &command, CommandReturnObject &result) override {
4828 Target *target = GetSelectedOrDummyTarget();
4829 if (!target) {
4830 result.AppendError("invalid target\n");
4831 result.SetStatus(eReturnStatusFailed);
4832 return result.Succeeded();
4833 }
4834
4835 size_t num_hooks = target->GetNumStopHooks();
4836 if (num_hooks == 0) {
4837 result.GetOutputStream().PutCString("No stop hooks.\n");
4838 } else {
4839 for (size_t i = 0; i < num_hooks; i++) {
4840 Target::StopHookSP this_hook = target->GetStopHookAtIndex(i);
4841 if (i > 0)
4842 result.GetOutputStream().PutCString("\n");
4843 this_hook->GetDescription(&(result.GetOutputStream()),
4844 eDescriptionLevelFull);
4845 }
4846 }
4847 result.SetStatus(eReturnStatusSuccessFinishResult);
4848 return result.Succeeded();
4849 }
4850};
4851
4852#pragma mark CommandObjectMultiwordTargetStopHooks
4853
4854//-------------------------------------------------------------------------
4855// CommandObjectMultiwordTargetStopHooks
4856//-------------------------------------------------------------------------
4857
4858class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword {
4859public:
4860 CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter)
4861 : CommandObjectMultiword(
4862 interpreter, "target stop-hook",
4863 "Commands for operating on debugger target stop-hooks.",
4864 "target stop-hook <subcommand> [<subcommand-options>]") {
4865 LoadSubCommand("add", CommandObjectSP(
4866 new CommandObjectTargetStopHookAdd(interpreter)));
4867 LoadSubCommand(
4868 "delete",
4869 CommandObjectSP(new CommandObjectTargetStopHookDelete(interpreter)));
4870 LoadSubCommand("disable",
4871 CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
4872 interpreter, false, "target stop-hook disable [<id>]",
4873 "Disable a stop-hook.", "target stop-hook disable")));
4874 LoadSubCommand("enable",
4875 CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
4876 interpreter, true, "target stop-hook enable [<id>]",
4877 "Enable a stop-hook.", "target stop-hook enable")));
4878 LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetStopHookList(
4879 interpreter)));
4880 }
4881
4882 ~CommandObjectMultiwordTargetStopHooks() override = default;
4883};
4884
4885#pragma mark CommandObjectMultiwordTarget
4886
4887//-------------------------------------------------------------------------
4888// CommandObjectMultiwordTarget
4889//-------------------------------------------------------------------------
4890
4891CommandObjectMultiwordTarget::CommandObjectMultiwordTarget(
4892 CommandInterpreter &interpreter)
4893 : CommandObjectMultiword(interpreter, "target",
4894 "Commands for operating on debugger targets.",
4895 "target <subcommand> [<subcommand-options>]") {
4896 LoadSubCommand("create",
4897 CommandObjectSP(new CommandObjectTargetCreate(interpreter)));
4898 LoadSubCommand("delete",
4899 CommandObjectSP(new CommandObjectTargetDelete(interpreter)));
4900 LoadSubCommand("list",
4901 CommandObjectSP(new CommandObjectTargetList(interpreter)));
4902 LoadSubCommand("select",
4903 CommandObjectSP(new CommandObjectTargetSelect(interpreter)));
4904 LoadSubCommand(
4905 "stop-hook",
4906 CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter)));
4907 LoadSubCommand("modules",
4908 CommandObjectSP(new CommandObjectTargetModules(interpreter)));
4909 LoadSubCommand("symbols",
4910 CommandObjectSP(new CommandObjectTargetSymbols(interpreter)));
4911 LoadSubCommand("variable",
4912 CommandObjectSP(new CommandObjectTargetVariable(interpreter)));
4913}
4914
4915CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget() = default;

/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;
13
Calling defaulted copy assignment operator for '__shared_ptr'
30
Returning; memory was released
35
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; }
26
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)
20
Assuming the condition is true
21
Taking true branch
42
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)
22
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,
23
Assuming the condition is true
24
Taking true branch
167 -1) == 1)
168 {
169 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
170 _M_destroy();
25
Calling '_Sp_counted_base::_M_destroy'
27
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)
15
Taking true branch
37
Taking true branch
699 {
700 if (__tmp != 0)
16
Assuming '__tmp' is equal to null
17
Taking false branch
38
Assuming '__tmp' is equal to null
39
Taking false branch
701 __tmp->_M_add_ref_copy();
702 if (_M_pi != 0)
18
Taking true branch
40
Taking true branch
703 _M_pi->_M_release();
19
Calling '_Sp_counted_base::_M_release'
28
Returning; memory was released
41
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;
14
Calling copy assignment operator for '__shared_count'
29
Returning; memory was released
36
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;
45
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())
43
Taking false branch
82 return __exchange_and_add(__mem, __val);
83 else
84 return __exchange_and_add_single(__mem, __val);
44
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