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