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

source code of lldb/source/Commands/CommandObjectTarget.cpp