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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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