Bug Summary

File:tools/lldb/source/Commands/CommandObjectTarget.cpp
Warning:line 67, column 29
Use of memory after it is freed

Annotated Source Code

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

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

1// shared_ptr and weak_ptr implementation -*- C++ -*-
2
3// Copyright (C) 2007-2017 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25// GCC Note: Based on files from version 1.32.0 of the Boost library.
26
27// shared_count.hpp
28// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29
30// shared_ptr.hpp
31// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32// Copyright (C) 2001, 2002, 2003 Peter Dimov
33
34// weak_ptr.hpp
35// Copyright (C) 2001, 2002, 2003 Peter Dimov
36
37// enable_shared_from_this.hpp
38// Copyright (C) 2002 Peter Dimov
39
40// Distributed under the Boost Software License, Version 1.0. (See
41// accompanying file LICENSE_1_0.txt or copy at
42// http://www.boost.org/LICENSE_1_0.txt)
43
44/** @file
45 * This is an internal header file, included by other library headers.
46 * Do not attempt to use it directly. @headername{memory}
47 */
48
49#ifndef _SHARED_PTR_H1
50#define _SHARED_PTR_H1 1
51
52#include <bits/shared_ptr_base.h>
53
54namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
55{
56_GLIBCXX_BEGIN_NAMESPACE_VERSION
57
58 /**
59 * @addtogroup pointer_abstractions
60 * @{
61 */
62
63 /// 20.7.2.2.11 shared_ptr I/O
64 template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
65 inline std::basic_ostream<_Ch, _Tr>&
66 operator<<(std::basic_ostream<_Ch, _Tr>& __os,
67 const __shared_ptr<_Tp, _Lp>& __p)
68 {
69 __os << __p.get();
70 return __os;
71 }
72
73 /// 20.7.2.2.10 shared_ptr get_deleter
74 template<typename _Del, typename _Tp, _Lock_policy _Lp>
75 inline _Del*
76 get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept
77 {
78#if __cpp_rtti199711
79 return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
80#else
81 return 0;
82#endif
83 }
84
85
86 /**
87 * @brief A smart pointer with reference-counted copy semantics.
88 *
89 * The object pointed to is deleted when the last shared_ptr pointing to
90 * it is destroyed or reset.
91 */
92 template<typename _Tp>
93 class shared_ptr : public __shared_ptr<_Tp>
94 {
95 template<typename... _Args>
96 using _Constructible = typename enable_if<
97 is_constructible<__shared_ptr<_Tp>, _Args...>::value
98 >::type;
99
100 template<typename _Arg>
101 using _Assignable = typename enable_if<
102 is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&
103 >::type;
104
105 public:
106
107 using element_type = typename __shared_ptr<_Tp>::element_type;
108
109#if __cplusplus201103L > 201402L
110# define __cpp_lib_shared_ptr_weak_type 201606
111 using weak_type = weak_ptr<_Tp>;
112#endif
113 /**
114 * @brief Construct an empty %shared_ptr.
115 * @post use_count()==0 && get()==0
116 */
117 constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }
118
119 shared_ptr(const shared_ptr&) noexcept = default;
120
121 /**
122 * @brief Construct a %shared_ptr that owns the pointer @a __p.
123 * @param __p A pointer that is convertible to element_type*.
124 * @post use_count() == 1 && get() == __p
125 * @throw std::bad_alloc, in which case @c delete @a __p is called.
126 */
127 template<typename _Yp, typename = _Constructible<_Yp*>>
128 explicit
129 shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
130
131 /**
132 * @brief Construct a %shared_ptr that owns the pointer @a __p
133 * and the deleter @a __d.
134 * @param __p A pointer.
135 * @param __d A deleter.
136 * @post use_count() == 1 && get() == __p
137 * @throw std::bad_alloc, in which case @a __d(__p) is called.
138 *
139 * Requirements: _Deleter's copy constructor and destructor must
140 * not throw
141 *
142 * __shared_ptr will release __p by calling __d(__p)
143 */
144 template<typename _Yp, typename _Deleter,
145 typename = _Constructible<_Yp*, _Deleter>>
146 shared_ptr(_Yp* __p, _Deleter __d)
147 : __shared_ptr<_Tp>(__p, std::move(__d)) { }
148
149 /**
150 * @brief Construct a %shared_ptr that owns a null pointer
151 * and the deleter @a __d.
152 * @param __p A null pointer constant.
153 * @param __d A deleter.
154 * @post use_count() == 1 && get() == __p
155 * @throw std::bad_alloc, in which case @a __d(__p) is called.
156 *
157 * Requirements: _Deleter's copy constructor and destructor must
158 * not throw
159 *
160 * The last owner will call __d(__p)
161 */
162 template<typename _Deleter>
163 shared_ptr(nullptr_t __p, _Deleter __d)
164 : __shared_ptr<_Tp>(__p, std::move(__d)) { }
165
166 /**
167 * @brief Construct a %shared_ptr that owns the pointer @a __p
168 * and the deleter @a __d.
169 * @param __p A pointer.
170 * @param __d A deleter.
171 * @param __a An allocator.
172 * @post use_count() == 1 && get() == __p
173 * @throw std::bad_alloc, in which case @a __d(__p) is called.
174 *
175 * Requirements: _Deleter's copy constructor and destructor must
176 * not throw _Alloc's copy constructor and destructor must not
177 * throw.
178 *
179 * __shared_ptr will release __p by calling __d(__p)
180 */
181 template<typename _Yp, typename _Deleter, typename _Alloc,
182 typename = _Constructible<_Yp*, _Deleter, _Alloc>>
183 shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
184 : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
185
186 /**
187 * @brief Construct a %shared_ptr that owns a null pointer
188 * and the deleter @a __d.
189 * @param __p A null pointer constant.
190 * @param __d A deleter.
191 * @param __a An allocator.
192 * @post use_count() == 1 && get() == __p
193 * @throw std::bad_alloc, in which case @a __d(__p) is called.
194 *
195 * Requirements: _Deleter's copy constructor and destructor must
196 * not throw _Alloc's copy constructor and destructor must not
197 * throw.
198 *
199 * The last owner will call __d(__p)
200 */
201 template<typename _Deleter, typename _Alloc>
202 shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
203 : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
204
205 // Aliasing constructor
206
207 /**
208 * @brief Constructs a %shared_ptr instance that stores @a __p
209 * and shares ownership with @a __r.
210 * @param __r A %shared_ptr.
211 * @param __p A pointer that will remain valid while @a *__r is valid.
212 * @post get() == __p && use_count() == __r.use_count()
213 *
214 * This can be used to construct a @c shared_ptr to a sub-object
215 * of an object managed by an existing @c shared_ptr.
216 *
217 * @code
218 * shared_ptr< pair<int,int> > pii(new pair<int,int>());
219 * shared_ptr<int> pi(pii, &pii->first);
220 * assert(pii.use_count() == 2);
221 * @endcode
222 */
223 template<typename _Yp>
224 shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
225 : __shared_ptr<_Tp>(__r, __p) { }
226
227 /**
228 * @brief If @a __r is empty, constructs an empty %shared_ptr;
229 * otherwise construct a %shared_ptr that shares ownership
230 * with @a __r.
231 * @param __r A %shared_ptr.
232 * @post get() == __r.get() && use_count() == __r.use_count()
233 */
234 template<typename _Yp,
235 typename = _Constructible<const shared_ptr<_Yp>&>>
236 shared_ptr(const shared_ptr<_Yp>& __r) noexcept
237 : __shared_ptr<_Tp>(__r) { }
238
239 /**
240 * @brief Move-constructs a %shared_ptr instance from @a __r.
241 * @param __r A %shared_ptr rvalue.
242 * @post *this contains the old value of @a __r, @a __r is empty.
243 */
244 shared_ptr(shared_ptr&& __r) noexcept
245 : __shared_ptr<_Tp>(std::move(__r)) { }
246
247 /**
248 * @brief Move-constructs a %shared_ptr instance from @a __r.
249 * @param __r A %shared_ptr rvalue.
250 * @post *this contains the old value of @a __r, @a __r is empty.
251 */
252 template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>>
253 shared_ptr(shared_ptr<_Yp>&& __r) noexcept
254 : __shared_ptr<_Tp>(std::move(__r)) { }
255
256 /**
257 * @brief Constructs a %shared_ptr that shares ownership with @a __r
258 * and stores a copy of the pointer stored in @a __r.
259 * @param __r A weak_ptr.
260 * @post use_count() == __r.use_count()
261 * @throw bad_weak_ptr when __r.expired(),
262 * in which case the constructor has no effect.
263 */
264 template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
265 explicit shared_ptr(const weak_ptr<_Yp>& __r)
266 : __shared_ptr<_Tp>(__r) { }
267
268#if _GLIBCXX_USE_DEPRECATED1
269 template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>>
270 shared_ptr(auto_ptr<_Yp>&& __r);
271#endif
272
273 // _GLIBCXX_RESOLVE_LIB_DEFECTS
274 // 2399. shared_ptr's constructor from unique_ptr should be constrained
275 template<typename _Yp, typename _Del,
276 typename = _Constructible<unique_ptr<_Yp, _Del>>>
277 shared_ptr(unique_ptr<_Yp, _Del>&& __r)
278 : __shared_ptr<_Tp>(std::move(__r)) { }
279
280#if __cplusplus201103L <= 201402L && _GLIBCXX_USE_DEPRECATED1
281 // This non-standard constructor exists to support conversions that
282 // were possible in C++11 and C++14 but are ill-formed in C++17.
283 // If an exception is thrown this constructor has no effect.
284 template<typename _Yp, typename _Del,
285 _Constructible<unique_ptr<_Yp, _Del>, __sp_array_delete>* = 0>
286 shared_ptr(unique_ptr<_Yp, _Del>&& __r)
287 : __shared_ptr<_Tp>(std::move(__r), __sp_array_delete()) { }
288#endif
289
290 /**
291 * @brief Construct an empty %shared_ptr.
292 * @post use_count() == 0 && get() == nullptr
293 */
294 constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
295
296 shared_ptr& operator=(const shared_ptr&) noexcept = default;
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.2.0/../../../../include/c++/7.2.0/bits/shared_ptr_base.h

1// shared_ptr and weak_ptr implementation details -*- C++ -*-
2
3// Copyright (C) 2007-2017 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25// GCC Note: Based on files from version 1.32.0 of the Boost library.
26
27// shared_count.hpp
28// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29
30// shared_ptr.hpp
31// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32// Copyright (C) 2001, 2002, 2003 Peter Dimov
33
34// weak_ptr.hpp
35// Copyright (C) 2001, 2002, 2003 Peter Dimov
36
37// enable_shared_from_this.hpp
38// Copyright (C) 2002 Peter Dimov
39
40// Distributed under the Boost Software License, Version 1.0. (See
41// accompanying file LICENSE_1_0.txt or copy at
42// http://www.boost.org/LICENSE_1_0.txt)
43
44/** @file bits/shared_ptr_base.h
45 * This is an internal header file, included by other library headers.
46 * Do not attempt to use it directly. @headername{memory}
47 */
48
49#ifndef _SHARED_PTR_BASE_H1
50#define _SHARED_PTR_BASE_H1 1
51
52#if __cpp_rtti199711
53# include <typeinfo>
54#endif
55#include <bits/allocated_ptr.h>
56#include <bits/refwrap.h>
57#include <bits/stl_function.h>
58#include <ext/aligned_buffer.h>
59
60namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
61{
62_GLIBCXX_BEGIN_NAMESPACE_VERSION
63
64#if _GLIBCXX_USE_DEPRECATED1
65 template<typename> class auto_ptr;
66#endif
67
68 /**
69 * @brief Exception possibly thrown by @c shared_ptr.
70 * @ingroup exceptions
71 */
72 class bad_weak_ptr : public std::exception
73 {
74 public:
75 virtual char const* what() const noexcept;
76
77 virtual ~bad_weak_ptr() noexcept;
78 };
79
80 // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
81 inline void
82 __throw_bad_weak_ptr()
83 { _GLIBCXX_THROW_OR_ABORT(bad_weak_ptr())(__builtin_abort()); }
84
85 using __gnu_cxx::_Lock_policy;
86 using __gnu_cxx::__default_lock_policy;
87 using __gnu_cxx::_S_single;
88 using __gnu_cxx::_S_mutex;
89 using __gnu_cxx::_S_atomic;
90
91 // Empty helper class except when the template argument is _S_mutex.
92 template<_Lock_policy _Lp>
93 class _Mutex_base
94 {
95 protected:
96 // The atomic policy uses fully-fenced builtins, single doesn't care.
97 enum { _S_need_barriers = 0 };
98 };
99
100 template<>
101 class _Mutex_base<_S_mutex>
102 : public __gnu_cxx::__mutex
103 {
104 protected:
105 // This policy is used when atomic builtins are not available.
106 // The replacement atomic operations might not have the necessary
107 // memory barriers.
108 enum { _S_need_barriers = 1 };
109 };
110
111 template<_Lock_policy _Lp = __default_lock_policy>
112 class _Sp_counted_base
113 : public _Mutex_base<_Lp>
114 {
115 public:
116 _Sp_counted_base() noexcept
117 : _M_use_count(1), _M_weak_count(1) { }
118
119 virtual
120 ~_Sp_counted_base() noexcept
121 { }
122
123 // Called when _M_use_count drops to zero, to release the resources
124 // managed by *this.
125 virtual void
126 _M_dispose() noexcept = 0;
127
128 // Called when _M_weak_count drops to zero.
129 virtual void
130 _M_destroy() noexcept
131 { delete this; }
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.2.0/../../../../include/c++/7.2.0/ext/atomicity.h

1// Support for atomic operations -*- C++ -*-
2
3// Copyright (C) 2004-2017 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file ext/atomicity.h
26 * This file is a GNU extension to the Standard C++ Library.
27 */
28
29#ifndef _GLIBCXX_ATOMICITY_H1
30#define _GLIBCXX_ATOMICITY_H1 1
31
32#pragma GCC system_header
33
34#include <bits/c++config.h>
35#include <bits/gthr.h>
36#include <bits/atomic_word.h>
37
38namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
39{
40_GLIBCXX_BEGIN_NAMESPACE_VERSION
41
42 // Functions for portable atomic access.
43 // To abstract locking primitives across all thread policies, use:
44 // __exchange_and_add_dispatch
45 // __atomic_add_dispatch
46#ifdef _GLIBCXX_ATOMIC_BUILTINS1
47 static inline _Atomic_word
48 __exchange_and_add(volatile _Atomic_word* __mem, int __val)
49 { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL4); }
50
51 static inline void
52 __atomic_add(volatile _Atomic_word* __mem, int __val)
53 { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL4); }
54#else
55 _Atomic_word
56 __attribute__ ((__unused__))
57 __exchange_and_add(volatile _Atomic_word*, int) throw ();
58
59 void
60 __attribute__ ((__unused__))
61 __atomic_add(volatile _Atomic_word*, int) throw ();
62#endif
63
64 static inline _Atomic_word
65 __exchange_and_add_single(_Atomic_word* __mem, int __val)
66 {
67 _Atomic_word __result = *__mem;
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