blob: 1f4d170e7b4ed7f10b33335cba34da72c3062e9f [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectImage.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 "CommandObjectImage.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/Args.h"
17#include "lldb/Interpreter/CommandContext.h"
18#include "lldb/Core/Options.h"
19#include "lldb/Interpreter/CommandReturnObject.h"
20#include "lldb/Core/FileSpec.h"
21#include "lldb/Symbol/LineTable.h"
22#include "lldb/Symbol/ObjectFile.h"
23#include "lldb/Core/RegularExpression.h"
24#include "lldb/Core/Stream.h"
25#include "lldb/Symbol/SymbolFile.h"
26#include "lldb/Symbol/SymbolVendor.h"
27#include "lldb/Core/Module.h"
28#include "lldb/Target/Process.h"
29#include "lldb/Target/Target.h"
30#include "lldb/Interpreter/CommandCompletions.h"
31
32using namespace lldb;
33using namespace lldb_private;
34
35//----------------------------------------------------------------------
36// Static Helper functions
37//----------------------------------------------------------------------
38static void
39DumpModuleArchitecture (Stream &strm, Module *module, uint32_t width)
40{
41 if (module)
42 {
43 if (width)
44 strm.Printf("%-*s", width, module->GetArchitecture().AsCString());
45 else
46 strm.PutCString(module->GetArchitecture().AsCString());
47 }
48}
49
50static void
51DumpModuleUUID (Stream &strm, Module *module)
52{
53 module->GetUUID().Dump (&strm);
54}
55
56static uint32_t
57DumpCompileUnitLineTable
58(
59 CommandContext *context,
60 Stream &strm,
61 Module *module,
62 const FileSpec &file_spec,
63 bool load_addresses
64)
65{
66 uint32_t num_matches = 0;
67 if (module)
68 {
69 SymbolContextList sc_list;
70 num_matches = module->ResolveSymbolContextsForFileSpec (file_spec,
71 0,
72 false,
73 eSymbolContextCompUnit,
74 sc_list);
75
76 for (uint32_t i=0; i<num_matches; ++i)
77 {
78 SymbolContext sc;
79 if (sc_list.GetContextAtIndex(i, sc))
80 {
81 if (i > 0)
82 strm << "\n\n";
83
84 strm << "Line table for " << *dynamic_cast<FileSpec*> (sc.comp_unit) << " in `"
85 << module->GetFileSpec().GetFilename() << "\n";
86 LineTable *line_table = sc.comp_unit->GetLineTable();
87 if (line_table)
88 line_table->GetDescription (&strm, context->GetExecutionContext().process, lldb::eDescriptionLevelBrief);
89 else
90 strm << "No line table";
91 }
92 }
93 }
94 return num_matches;
95}
96
97static void
98DumpFullpath (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
99{
100 if (file_spec_ptr)
101 {
102 if (width > 0)
103 {
104 char fullpath[PATH_MAX];
105 if (file_spec_ptr->GetPath(fullpath, sizeof(fullpath)))
106 {
107 strm.Printf("%-*s", width, fullpath);
108 return;
109 }
110 }
111 else
112 {
113 file_spec_ptr->Dump(&strm);
114 return;
115 }
116 }
117 // Keep the width spacing correct if things go wrong...
118 if (width > 0)
119 strm.Printf("%-*s", width, "");
120}
121
122static void
123DumpDirectory (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
124{
125 if (file_spec_ptr)
126 {
127 if (width > 0)
128 strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
129 else
130 file_spec_ptr->GetDirectory().Dump(&strm);
131 return;
132 }
133 // Keep the width spacing correct if things go wrong...
134 if (width > 0)
135 strm.Printf("%-*s", width, "");
136}
137
138static void
139DumpBasename (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
140{
141 if (file_spec_ptr)
142 {
143 if (width > 0)
144 strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
145 else
146 file_spec_ptr->GetFilename().Dump(&strm);
147 return;
148 }
149 // Keep the width spacing correct if things go wrong...
150 if (width > 0)
151 strm.Printf("%-*s", width, "");
152}
153
154
155static void
156DumpModuleSymtab (CommandContext *context, Stream &strm, Module *module)
157{
158 if (module)
159 {
160 ObjectFile *objfile = module->GetObjectFile ();
161 if (objfile)
162 {
163 Symtab *symtab = objfile->GetSymtab();
164 if (symtab)
165 symtab->Dump(&strm, context->GetExecutionContext().process);
166 }
167 }
168}
169
170static void
171DumpModuleSections (CommandContext *context, Stream &strm, Module *module)
172{
173 if (module)
174 {
175 ObjectFile *objfile = module->GetObjectFile ();
176 if (objfile)
177 {
178 SectionList *section_list = objfile->GetSectionList();
179 if (section_list)
180 section_list->Dump(&strm, context->GetExecutionContext().process, true);
181 }
182 }
183}
184
185static bool
186DumpModuleSymbolVendor (Stream &strm, Module *module)
187{
188 if (module)
189 {
190 SymbolVendor *symbol_vendor = module->GetSymbolVendor(true);
191 if (symbol_vendor)
192 {
193 symbol_vendor->Dump(&strm);
194 return true;
195 }
196 }
197 return false;
198}
199
200static bool
201LookupAddressInModule (CommandContext *context, Stream &strm, Module *module, uint32_t resolve_mask, lldb::addr_t raw_addr, lldb::addr_t offset)
202{
203 if (module)
204 {
205 lldb::addr_t addr = raw_addr - offset;
206 Address so_addr;
207 SymbolContext sc;
208 Process *process = context->GetExecutionContext().process;
209 if (process && process->IsAlive())
210 {
211 if (!process->ResolveLoadAddress (addr, so_addr))
212 return false;
213 else if (so_addr.GetModule() != module)
214 return false;
215 }
216 else
217 {
218 if (!module->ResolveFileAddress (addr, so_addr))
219 return false;
220 }
221
222 // If an offset was given, print out the address we ended up looking up
223 if (offset)
224 strm.Printf("0x%llx: ", addr);
225
226 ExecutionContextScope *exe_scope = context->GetExecutionContext().GetBestExecutionContextScope();
227 if (so_addr.Dump (&strm, exe_scope, Address::DumpStyleSectionNameOffset))
228 strm.PutCString(": ");
229 so_addr.Dump (&strm, exe_scope, Address::DumpStyleResolvedDescription);
230 return true;
231 }
232
233 return false;
234}
235
236static uint32_t
237LookupSymbolInModule (CommandContext *context, Stream &strm, Module *module, const char *name, bool name_is_regex)
238{
239 if (module)
240 {
241 SymbolContext sc;
242
243 ObjectFile *objfile = module->GetObjectFile ();
244 if (objfile)
245 {
246 Symtab *symtab = objfile->GetSymtab();
247 if (symtab)
248 {
249 uint32_t i;
250 std::vector<uint32_t> match_indexes;
251 ConstString symbol_name (name);
252 uint32_t num_matches = 0;
253 if (name_is_regex)
254 {
255 RegularExpression name_regexp(name);
256 num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType (name_regexp, eSymbolTypeAny,
257 match_indexes);
258 }
259 else
260 {
261 num_matches = symtab->AppendSymbolIndexesWithName (symbol_name, match_indexes);
262 }
263
264
265 if (num_matches > 0)
266 {
267 strm.Indent ();
268 strm.Printf("%u symbols match %s'%s' in ", num_matches,
269 name_is_regex ? "the regular expression " : "", name);
270 DumpFullpath (strm, &module->GetFileSpec(), 0);
271 strm.PutCString(":\n");
272 strm.IndentMore ();
273 Symtab::DumpSymbolHeader (&strm);
274 for (i=0; i < num_matches; ++i)
275 {
276 Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
277 strm.Indent ();
278 symbol->Dump (&strm, context->GetExecutionContext().process, i);
279 }
280 strm.IndentLess ();
281 return num_matches;
282 }
283 }
284 }
285 }
286 return 0;
287}
288
289
290static void
291DumpSymbolContextList (CommandContext *context, Stream &strm, SymbolContextList &sc_list, bool prepend_addr)
292{
293 strm.IndentMore ();
294 uint32_t i;
295 const uint32_t num_matches = sc_list.GetSize();
296
297 for (i=0; i<num_matches; ++i)
298 {
299 SymbolContext sc;
300 if (sc_list.GetContextAtIndex(i, sc))
301 {
302 strm.Indent();
303 if (prepend_addr)
304 {
305 if (sc.line_entry.range.GetBaseAddress().IsValid())
306 {
307 lldb::addr_t vm_addr =
308 sc.line_entry.range.GetBaseAddress().GetLoadAddress(context->GetExecutionContext().process);
309 int addr_size = sizeof (addr_t);
310 Process *process = context->GetExecutionContext().process;
311 if (process)
312 addr_size = process->GetAddressByteSize();
313 if (vm_addr != LLDB_INVALID_ADDRESS)
314 strm.Address (vm_addr, addr_size);
315 else
316 sc.line_entry.range.GetBaseAddress().Dump (&strm, NULL, Address::DumpStyleSectionNameOffset);
317
318 strm.PutCString(" in ");
319 }
320 }
321 sc.DumpStopContext(&strm, context->GetExecutionContext().process, sc.line_entry.range.GetBaseAddress());
322 }
323 }
324 strm.IndentLess ();
325}
326
327static uint32_t
328LookupFunctionInModule (CommandContext *context, Stream &strm, Module *module, const char *name, bool name_is_regex)
329{
330 if (module && name && name[0])
331 {
332 SymbolContextList sc_list;
333
334 SymbolVendor *symbol_vendor = module->GetSymbolVendor();
335 if (symbol_vendor)
336 {
337 uint32_t num_matches = 0;
338 if (name_is_regex)
339 {
340 RegularExpression function_name_regex (name);
341 num_matches = symbol_vendor->FindFunctions(function_name_regex, true, sc_list);
342
343 }
344 else
345 {
346 ConstString function_name(name);
347 num_matches = symbol_vendor->FindFunctions(function_name, true, sc_list);
348 }
349
350 if (num_matches)
351 {
352 strm.Indent ();
353 strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
354 DumpFullpath (strm, &module->GetFileSpec(), 0);
355 strm.PutCString(":\n");
356 DumpSymbolContextList (context, strm, sc_list, true);
357 }
358 return num_matches;
359 }
360 }
361 return 0;
362}
363
364static uint32_t
365LookupFileAndLineInModule (CommandContext *context, Stream &strm, Module *module, const FileSpec &file_spec, uint32_t line, bool check_inlines)
366{
367 if (module && file_spec)
368 {
369 SymbolContextList sc_list;
370 const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
371 eSymbolContextEverything, sc_list);
372 if (num_matches > 0)
373 {
374 strm.Indent ();
375 strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
376 strm << file_spec;
377 if (line > 0)
378 strm.Printf (":%u", line);
379 strm << " in ";
380 DumpFullpath (strm, &module->GetFileSpec(), 0);
381 strm.PutCString(":\n");
382 DumpSymbolContextList (context, strm, sc_list, true);
383 return num_matches;
384 }
385 }
386 return 0;
387
388}
389
390
391//----------------------------------------------------------------------
392// Image symbol table dumping command
393//----------------------------------------------------------------------
394
395class CommandObjectImageDumpModuleList : public CommandObject
396{
397public:
398
399 CommandObjectImageDumpModuleList (const char *name,
400 const char *help,
401 const char *syntax) :
402 CommandObject (name, help, syntax)
403 {
404 }
405
406 virtual
407 ~CommandObjectImageDumpModuleList ()
408 {
409 }
410
411 virtual int
412 HandleArgumentCompletion (Args &input,
413 int &cursor_index,
414 int &cursor_char_position,
415 OptionElementVector &opt_element_vector,
416 int match_start_point,
417 int max_return_elements,
418 CommandInterpreter *interpreter,
419 StringList &matches)
420 {
421 // Arguments are the standard module completer.
422 std::string completion_str (input.GetArgumentAtIndex(cursor_index));
423 completion_str.erase (cursor_char_position);
424
425 CommandCompletions::InvokeCommonCompletionCallbacks (CommandCompletions::eModuleCompletion,
426 completion_str.c_str(),
427 match_start_point,
428 max_return_elements,
429 interpreter,
430 NULL,
431 matches);
432 return matches.GetSize();
433 }
434};
435
436class CommandObjectImageDumpSourceFileList : public CommandObject
437{
438public:
439
440 CommandObjectImageDumpSourceFileList (const char *name,
441 const char *help,
442 const char *syntax) :
443 CommandObject (name, help, syntax)
444 {
445 }
446
447 virtual
448 ~CommandObjectImageDumpSourceFileList ()
449 {
450 }
451
452 virtual int
453 HandleArgumentCompletion (Args &input,
454 int &cursor_index,
455 int &cursor_char_position,
456 OptionElementVector &opt_element_vector,
457 int match_start_point,
458 int max_return_elements,
459 CommandInterpreter *interpreter,
460 StringList &matches)
461 {
462 // Arguments are the standard source file completer.
463 std::string completion_str (input.GetArgumentAtIndex(cursor_index));
464 completion_str.erase (cursor_char_position);
465
466 CommandCompletions::InvokeCommonCompletionCallbacks (CommandCompletions::eSourceFileCompletion,
467 completion_str.c_str(),
468 match_start_point,
469 max_return_elements,
470 interpreter,
471 NULL,
472 matches);
473 return matches.GetSize();
474 }
475};
476
477
478class CommandObjectImageDumpSymtab : public CommandObjectImageDumpModuleList
479{
480public:
481 CommandObjectImageDumpSymtab () :
482 CommandObjectImageDumpModuleList ("image dump symtab",
483 "Dump the symbol table from one or more executable images.",
484 "image dump symtab [<file1> ...]")
485 {
486 }
487
488 virtual
489 ~CommandObjectImageDumpSymtab ()
490 {
491 }
492
493 virtual bool
494 Execute (Args& command,
495 CommandContext *context,
496 CommandInterpreter *interpreter,
497 CommandReturnObject &result)
498 {
499 Target *target = context->GetTarget();
500 if (target == NULL)
501 {
502 result.AppendError ("invalid target, set executable file using 'file' command");
503 result.SetStatus (eReturnStatusFailed);
504 return false;
505 }
506 else
507 {
508 uint32_t num_dumped = 0;
509
510 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
511 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
512 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
513
514 if (command.GetArgumentCount() == 0)
515 {
516 // Dump all sections for all modules images
517 const uint32_t num_modules = target->GetImages().GetSize();
518 if (num_modules > 0)
519 {
520 result.GetOutputStream().Printf("Dumping symbol table for %u modules.\n", num_modules);
521 for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
522 {
523 num_dumped++;
524 DumpModuleSymtab (context, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx));
525 }
526 }
527 else
528 {
529 result.AppendError ("the target has no associated executable images");
530 result.SetStatus (eReturnStatusFailed);
531 return false;
532 }
533 }
534 else
535 {
536 // Dump specified images (by basename or fullpath)
537 const char *arg_cstr;
538 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
539 {
540 FileSpec image_file(arg_cstr);
541 ModuleList matching_modules;
542 const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
543
544 if (num_matching_modules > 0)
545 {
546 for (size_t i=0; i<num_matching_modules; ++i)
547 {
548 Module *image_module = matching_modules.GetModulePointerAtIndex(i);
549 if (image_module)
550 {
551 num_dumped++;
552 DumpModuleSymtab (context, result.GetOutputStream(), image_module);
553 }
554 }
555 }
556 else
557 result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
558 }
559 }
560
561 if (num_dumped > 0)
562 result.SetStatus (eReturnStatusSuccessFinishResult);
563 else
564 {
565 result.AppendError ("no matching executable images found");
566 result.SetStatus (eReturnStatusFailed);
567 }
568 }
569 return result.Succeeded();
570 }
571
572};
573
574//----------------------------------------------------------------------
575// Image section dumping command
576//----------------------------------------------------------------------
577class CommandObjectImageDumpSections : public CommandObjectImageDumpModuleList
578{
579public:
580 CommandObjectImageDumpSections () :
581 CommandObjectImageDumpModuleList (
582 "image dump sections",
583 "Dump the sections from one or more executable images.",
584 "image dump sections [<file1> ...]")
585 {
586 }
587
588 virtual
589 ~CommandObjectImageDumpSections ()
590 {
591 }
592
593 virtual bool
594 Execute (Args& command,
595 CommandContext *context,
596 CommandInterpreter *interpreter,
597 CommandReturnObject &result)
598 {
599 Target *target = context->GetTarget();
600 if (target == NULL)
601 {
602 result.AppendError ("invalid target, set executable file using 'file' command");
603 result.SetStatus (eReturnStatusFailed);
604 return false;
605 }
606 else
607 {
608 uint32_t num_dumped = 0;
609
610 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
611 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
612 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
613
614 if (command.GetArgumentCount() == 0)
615 {
616 // Dump all sections for all modules images
617 const uint32_t num_modules = target->GetImages().GetSize();
618 if (num_modules > 0)
619 {
620 result.GetOutputStream().Printf("Dumping sections for %u modules.\n", num_modules);
621 for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
622 {
623 num_dumped++;
624 DumpModuleSections (context, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx));
625 }
626 }
627 else
628 {
629 result.AppendError ("the target has no associated executable images");
630 result.SetStatus (eReturnStatusFailed);
631 return false;
632 }
633 }
634 else
635 {
636 // Dump specified images (by basename or fullpath)
637 const char *arg_cstr;
638 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
639 {
640 FileSpec image_file(arg_cstr);
641 ModuleList matching_modules;
642 const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
643
644 if (num_matching_modules > 0)
645 {
646 for (size_t i=0; i<num_matching_modules; ++i)
647 {
648 Module * image_module = matching_modules.GetModulePointerAtIndex(i);
649 if (image_module)
650 {
651 num_dumped++;
652 DumpModuleSections (context, result.GetOutputStream(), image_module);
653 }
654 }
655 }
656 else
657 result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
658 }
659 }
660
661 if (num_dumped > 0)
662 result.SetStatus (eReturnStatusSuccessFinishResult);
663 else
664 {
665 result.AppendError ("no matching executable images found");
666 result.SetStatus (eReturnStatusFailed);
667 }
668 }
669 return result.Succeeded();
670 }
671};
672
673//----------------------------------------------------------------------
674// Image debug symbol dumping command
675//----------------------------------------------------------------------
676class CommandObjectImageDumpSymfile : public CommandObjectImageDumpModuleList
677{
678public:
679 CommandObjectImageDumpSymfile () :
680 CommandObjectImageDumpModuleList ("image dump symfile",
681 "Dump the debug symbol file for one or more executable images.",
682 "image dump symfile [<file1> ...]")
683 {
684 }
685
686 virtual
687 ~CommandObjectImageDumpSymfile ()
688 {
689 }
690
691 virtual bool
692 Execute (Args& command,
693 CommandContext *context,
694 CommandInterpreter *interpreter,
695 CommandReturnObject &result)
696 {
697 Target *target = context->GetTarget();
698 if (target == NULL)
699 {
700 result.AppendError ("invalid target, set executable file using 'file' command");
701 result.SetStatus (eReturnStatusFailed);
702 return false;
703 }
704 else
705 {
706 uint32_t num_dumped = 0;
707
708 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
709 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
710 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
711
712 if (command.GetArgumentCount() == 0)
713 {
714 // Dump all sections for all modules images
715 const uint32_t num_modules = target->GetImages().GetSize();
716 if (num_modules > 0)
717 {
718 result.GetOutputStream().Printf("Dumping debug symbols for %u modules.\n", num_modules);
719 for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
720 {
721 if (DumpModuleSymbolVendor (result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx)))
722 num_dumped++;
723 }
724 }
725 else
726 {
727 result.AppendError ("the target has no associated executable images");
728 result.SetStatus (eReturnStatusFailed);
729 return false;
730 }
731 }
732 else
733 {
734 // Dump specified images (by basename or fullpath)
735 const char *arg_cstr;
736 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
737 {
738 FileSpec image_file(arg_cstr);
739 ModuleList matching_modules;
740 const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
741
742 if (num_matching_modules > 0)
743 {
744 for (size_t i=0; i<num_matching_modules; ++i)
745 {
746 Module * image_module = matching_modules.GetModulePointerAtIndex(i);
747 if (image_module)
748 {
749 if (DumpModuleSymbolVendor (result.GetOutputStream(), image_module))
750 num_dumped++;
751 }
752 }
753 }
754 else
755 result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
756 }
757 }
758
759 if (num_dumped > 0)
760 result.SetStatus (eReturnStatusSuccessFinishResult);
761 else
762 {
763 result.AppendError ("no matching executable images found");
764 result.SetStatus (eReturnStatusFailed);
765 }
766 }
767 return result.Succeeded();
768 }
769};
770
771//----------------------------------------------------------------------
772// Image debug symbol dumping command
773//----------------------------------------------------------------------
774class CommandObjectImageDumpLineTable : public CommandObjectImageDumpSourceFileList
775{
776public:
777 CommandObjectImageDumpLineTable () :
778 CommandObjectImageDumpSourceFileList ("image dump line-table",
779 "Dump the debug symbol file for one or more executable images.",
780 "image dump line-table <file1> [<file2> ...]")
781 {
782 }
783
784 virtual
785 ~CommandObjectImageDumpLineTable ()
786 {
787 }
788
789 virtual bool
790 Execute (Args& command,
791 CommandContext *context,
792 CommandInterpreter *interpreter,
793 CommandReturnObject &result)
794 {
795 Target *target = context->GetTarget();
796 if (target == NULL)
797 {
798 result.AppendError ("invalid target, set executable file using 'file' command");
799 result.SetStatus (eReturnStatusFailed);
800 return false;
801 }
802 else
803 {
804 ExecutionContext exe_ctx(context->GetExecutionContext());
805 uint32_t total_num_dumped = 0;
806
807 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
808 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
809 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
810
811 if (command.GetArgumentCount() == 0)
812 {
813 result.AppendErrorWithFormat ("\nSyntax: %s\n", m_cmd_syntax.c_str());
814 result.SetStatus (eReturnStatusFailed);
815 }
816 else
817 {
818 // Dump specified images (by basename or fullpath)
819 const char *arg_cstr;
820 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
821 {
822 FileSpec file_spec(arg_cstr);
823 const uint32_t num_modules = target->GetImages().GetSize();
824 if (num_modules > 0)
825 {
826 uint32_t num_dumped = 0;
827 for (uint32_t i = 0; i<num_modules; ++i)
828 {
829 if (DumpCompileUnitLineTable (context,
830 result.GetOutputStream(),
831 target->GetImages().GetModulePointerAtIndex(i),
832 file_spec,
833 exe_ctx.process != NULL && exe_ctx.process->IsAlive()))
834 num_dumped++;
835 }
836 if (num_dumped == 0)
837 result.AppendWarningWithFormat ("No source filenames matched '%s'.\n", arg_cstr);
838 else
839 total_num_dumped += num_dumped;
840 }
841 }
842 }
843
844 if (total_num_dumped > 0)
845 result.SetStatus (eReturnStatusSuccessFinishResult);
846 else
847 {
848 result.AppendError ("no source filenames matched any command arguments");
849 result.SetStatus (eReturnStatusFailed);
850 }
851 }
852 return result.Succeeded();
853 }
854};
855
856//----------------------------------------------------------------------
857// Dump multi-word command
858//----------------------------------------------------------------------
859class CommandObjectImageDump : public CommandObjectMultiword
860{
861public:
862
863 //------------------------------------------------------------------
864 // Constructors and Destructors
865 //------------------------------------------------------------------
866 CommandObjectImageDump(CommandInterpreter *interpreter) :
867 CommandObjectMultiword ("image dump",
868 "Dumps information in one or more executable images; 'line-table' expects a source file name",
869 "image dump [symtab|sections|symfile|line-table] [<file1> <file2> ...]")
870 {
871 LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpSymtab ()), "symtab", interpreter);
872 LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpSections ()), "sections", interpreter);
873 LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpSymfile ()), "symfile", interpreter);
874 LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpLineTable ()), "line-table", interpreter);
875 }
876
877 virtual
878 ~CommandObjectImageDump()
879 {
880 }
881};
882
883//----------------------------------------------------------------------
884// List images with associated information
885//----------------------------------------------------------------------
886class CommandObjectImageList : public CommandObject
887{
888public:
889
890 class CommandOptions : public Options
891 {
892 public:
893
894 CommandOptions () :
895 Options(),
896 m_format_array()
897 {
898 }
899
900 virtual
901 ~CommandOptions ()
902 {
903 }
904
905 virtual Error
906 SetOptionValue (int option_idx, const char *option_arg)
907 {
908 char short_option = (char) m_getopt_table[option_idx].val;
909 uint32_t width = 0;
910 if (option_arg)
911 width = strtoul (option_arg, NULL, 0);
912 m_format_array.push_back(std::make_pair(short_option, width));
913 Error error;
914 return error;
915 }
916
917 void
918 ResetOptionValues ()
919 {
920 Options::ResetOptionValues();
921 m_format_array.clear();
922 }
923
924 const lldb::OptionDefinition*
925 GetDefinitions ()
926 {
927 return g_option_table;
928 }
929
930 // Options table: Required for subclasses of Options.
931
932 static lldb::OptionDefinition g_option_table[];
933
934 // Instance variables to hold the values for command options.
935 typedef std::vector< std::pair<char, uint32_t> > FormatWidthCollection;
936 FormatWidthCollection m_format_array;
937 };
938
939 CommandObjectImageList () :
940 CommandObject (
941 "image list",
942 "List current executable and dependent shared library images.",
943 "image list [<cmd-options>]")
944 {
945 }
946
947 virtual
948 ~CommandObjectImageList ()
949 {
950 }
951
952 virtual
953 Options *
954 GetOptions ()
955 {
956 return &m_options;
957 }
958
959 virtual bool
960 Execute (Args& command,
961 CommandContext *context,
962 CommandInterpreter *interpreter,
963 CommandReturnObject &result)
964 {
965 Target *target = context->GetTarget();
966 if (target == NULL)
967 {
968 result.AppendError ("invalid target, set executable file using 'file' command");
969 result.SetStatus (eReturnStatusFailed);
970 return false;
971 }
972 else
973 {
974 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
975 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
976 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
977 // Dump all sections for all modules images
978 const uint32_t num_modules = target->GetImages().GetSize();
979 if (num_modules > 0)
980 {
981 Stream &strm = result.GetOutputStream();
982
983 for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
984 {
985 Module *module = target->GetImages().GetModulePointerAtIndex(image_idx);
986 strm.Printf("[%3u] ", image_idx);
987
988 if (m_options.m_format_array.empty())
989 {
990 DumpFullpath(strm, &module->GetFileSpec(), 0);
991 }
992 else
993 {
994 const size_t num_entries = m_options.m_format_array.size();
995 for (size_t i=0; i<num_entries; ++i)
996 {
997 if (i > 0)
998 strm.PutChar(' ');
999 char format_char = m_options.m_format_array[i].first;
1000 uint32_t width = m_options.m_format_array[i].second;
1001 switch (format_char)
1002 {
1003 case 'a':
1004 DumpModuleArchitecture (strm, module, width);
1005 break;
1006
1007 case 'f':
1008 DumpFullpath (strm, &module->GetFileSpec(), width);
1009 break;
1010
1011 case 'd':
1012 DumpDirectory (strm, &module->GetFileSpec(), width);
1013 break;
1014
1015 case 'b':
1016 DumpBasename (strm, &module->GetFileSpec(), width);
1017 break;
1018
1019 case 's':
1020 case 'S':
1021 {
1022 SymbolVendor *symbol_vendor = module->GetSymbolVendor();
1023 if (symbol_vendor)
1024 {
1025 SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
1026 if (symbol_file)
1027 {
1028 if (format_char == 'S')
1029 DumpBasename(strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
1030 else
1031 DumpFullpath (strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
1032 break;
1033 }
1034 }
1035 strm.Printf("%.*s", width, "<NONE>");
1036 }
1037 break;
1038
1039 case 'u':
1040 DumpModuleUUID(strm, module);
1041 break;
1042
1043 default:
1044 break;
1045 }
1046 }
1047 }
1048 strm.EOL();
1049 }
1050 result.SetStatus (eReturnStatusSuccessFinishResult);
1051 }
1052 else
1053 {
1054 result.AppendError ("the target has no associated executable images");
1055 result.SetStatus (eReturnStatusFailed);
1056 return false;
1057 }
1058 }
1059 return result.Succeeded();
1060 }
1061protected:
1062
1063 CommandOptions m_options;
1064};
1065
1066lldb::OptionDefinition
1067CommandObjectImageList::CommandOptions::g_option_table[] =
1068{
Jim Ingham34e9a982010-06-15 18:47:14 +00001069{ LLDB_OPT_SET_1, false, "arch", 'a', optional_argument, NULL, 0, "<width>", "Display the architecture when listing images."},
1070{ LLDB_OPT_SET_1, false, "uuid", 'u', no_argument, NULL, 0, NULL, "Display the UUID when listing images."},
1071{ LLDB_OPT_SET_1, false, "fullpath", 'f', optional_argument, NULL, 0, "<width>", "Display the fullpath to the image object file."},
1072{ LLDB_OPT_SET_1, false, "directory", 'd', optional_argument, NULL, 0, "<width>", "Display the directory with optional width for the image object file."},
1073{ LLDB_OPT_SET_1, false, "basename", 'b', optional_argument, NULL, 0, "<width>", "Display the basename with optional width for the image object file."},
1074{ LLDB_OPT_SET_1, false, "symfile", 's', optional_argument, NULL, 0, "<width>", "Display the fullpath to the image symbol file with optional width."},
1075{ LLDB_OPT_SET_1, false, "symfile-basename", 'S', optional_argument, NULL, 0, "<width>", "Display the basename to the image symbol file with optional width."},
Chris Lattner24943d22010-06-08 16:52:24 +00001076{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
1077};
1078
1079
1080
1081//----------------------------------------------------------------------
1082// Lookup information in images
1083//----------------------------------------------------------------------
1084class CommandObjectImageLookup : public CommandObject
1085{
1086public:
1087
1088 enum
1089 {
1090 eLookupTypeInvalid = -1,
1091 eLookupTypeAddress = 0,
1092 eLookupTypeSymbol,
1093 eLookupTypeFileLine, // Line is optional
1094 eLookupTypeFunction,
1095 kNumLookupTypes
1096 };
1097
1098 class CommandOptions : public Options
1099 {
1100 public:
1101
1102 CommandOptions () :
1103 Options()
1104 {
1105 ResetOptionValues();
1106 }
1107
1108 virtual
1109 ~CommandOptions ()
1110 {
1111 }
1112
1113 virtual Error
1114 SetOptionValue (int option_idx, const char *option_arg)
1115 {
1116 Error error;
1117
1118 char short_option = (char) m_getopt_table[option_idx].val;
1119
1120 switch (short_option)
1121 {
1122 case 'a':
1123 m_type = eLookupTypeAddress;
1124 m_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
1125 if (m_addr == LLDB_INVALID_ADDRESS)
1126 error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", option_arg);
1127 break;
1128
1129 case 'o':
1130 m_offset = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
1131 if (m_offset == LLDB_INVALID_ADDRESS)
1132 error.SetErrorStringWithFormat ("Invalid offset string '%s'.\n", option_arg);
1133 break;
1134
1135 case 's':
1136 m_str = option_arg;
1137 m_type = eLookupTypeSymbol;
1138 break;
1139
1140 case 'f':
1141 m_file.SetFile (option_arg);
1142 m_type = eLookupTypeFileLine;
1143 break;
1144
1145 case 'i':
1146 m_check_inlines = false;
1147 break;
1148
1149 case 'l':
1150 m_line_number = Args::StringToUInt32(option_arg, UINT32_MAX);
1151 if (m_line_number == UINT32_MAX)
1152 error.SetErrorStringWithFormat ("Invalid line number string '%s'.\n", option_arg);
1153 else if (m_line_number == 0)
1154 error.SetErrorString ("Zero is an invalid line number.");
1155 m_type = eLookupTypeFileLine;
1156 break;
1157
1158 case 'n':
1159 m_str = option_arg;
1160 m_type = eLookupTypeFunction;
1161 break;
1162
1163 case 'r':
1164 m_use_regex = true;
1165 break;
1166 }
1167
1168 return error;
1169 }
1170
1171 void
1172 ResetOptionValues ()
1173 {
1174 Options::ResetOptionValues();
1175 m_type = eLookupTypeInvalid;
1176 m_str.clear();
1177 m_file.Clear();
1178 m_addr = LLDB_INVALID_ADDRESS;
1179 m_offset = 0;
1180 m_line_number = 0;
1181 m_use_regex = false;
1182 m_check_inlines = true;
1183 }
1184
1185 const lldb::OptionDefinition*
1186 GetDefinitions ()
1187 {
1188 return g_option_table;
1189 }
1190
1191 // Options table: Required for subclasses of Options.
1192
1193 static lldb::OptionDefinition g_option_table[];
1194 int m_type; // Should be a eLookupTypeXXX enum after parsing options
1195 std::string m_str; // Holds name lookup
1196 FileSpec m_file; // Files for file lookups
1197 lldb::addr_t m_addr; // Holds the address to lookup
1198 lldb::addr_t m_offset; // Subtract this offset from m_addr before doing lookups.
1199 uint32_t m_line_number; // Line number for file+line lookups
1200 bool m_use_regex; // Name lookups in m_str are regular expressions.
1201 bool m_check_inlines;// Check for inline entries when looking up by file/line.
1202 };
1203
1204 CommandObjectImageLookup () :
1205 CommandObject (
1206 "image lookup",
1207 "Look up information within executable and dependent shared library images.",
1208 "image lookup [<cmd-options>] [<file1>...]")
1209 {
1210 }
1211
1212 virtual
1213 ~CommandObjectImageLookup ()
1214 {
1215 }
1216
1217 virtual
1218 Options *
1219 GetOptions ()
1220 {
1221 return &m_options;
1222 }
1223
1224
1225 bool
1226 LookupInModule (CommandContext *context, Module *module, CommandReturnObject &result, bool &syntax_error)
1227 {
1228 switch (m_options.m_type)
1229 {
1230 case eLookupTypeAddress:
1231 if (m_options.m_addr != LLDB_INVALID_ADDRESS)
1232 {
1233 if (LookupAddressInModule (context, result.GetOutputStream(), module, eSymbolContextEverything, m_options.m_addr, m_options.m_offset))
1234 {
1235 result.SetStatus(eReturnStatusSuccessFinishResult);
1236 return true;
1237 }
1238 }
1239 break;
1240
1241 case eLookupTypeSymbol:
1242 if (!m_options.m_str.empty())
1243 {
1244 if (LookupSymbolInModule (context, result.GetOutputStream(), module, m_options.m_str.c_str(), m_options.m_use_regex))
1245 {
1246 result.SetStatus(eReturnStatusSuccessFinishResult);
1247 return true;
1248 }
1249 }
1250 break;
1251
1252 case eLookupTypeFileLine:
1253 if (m_options.m_file)
1254 {
1255
1256 if (LookupFileAndLineInModule (context,
1257 result.GetOutputStream(),
1258 module,
1259 m_options.m_file,
1260 m_options.m_line_number,
1261 m_options.m_check_inlines))
1262 {
1263 result.SetStatus(eReturnStatusSuccessFinishResult);
1264 return true;
1265 }
1266 }
1267 break;
1268
1269 case eLookupTypeFunction:
1270 if (!m_options.m_str.empty())
1271 {
1272 if (LookupFunctionInModule (context,
1273 result.GetOutputStream(),
1274 module,
1275 m_options.m_str.c_str(),
1276 m_options.m_use_regex))
1277 {
1278 result.SetStatus(eReturnStatusSuccessFinishResult);
1279 return true;
1280 }
1281 }
1282 break;
1283
1284 default:
1285 m_options.GenerateOptionUsage (result.GetErrorStream(), this);
1286 syntax_error = true;
1287 break;
1288 }
1289
1290 result.SetStatus (eReturnStatusFailed);
1291 return false;
1292 }
1293
1294 virtual bool
1295 Execute (Args& command,
1296 CommandContext *context,
1297 CommandInterpreter *interpreter,
1298 CommandReturnObject &result)
1299 {
1300 Target *target = context->GetTarget();
1301 if (target == NULL)
1302 {
1303 result.AppendError ("invalid target, set executable file using 'file' command");
1304 result.SetStatus (eReturnStatusFailed);
1305 return false;
1306 }
1307 else
1308 {
1309 bool syntax_error = false;
1310 uint32_t i;
1311 uint32_t num_successful_lookups = 0;
1312 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
1313 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
1314 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
1315 // Dump all sections for all modules images
1316
1317 if (command.GetArgumentCount() == 0)
1318 {
1319 // Dump all sections for all modules images
1320 const uint32_t num_modules = target->GetImages().GetSize();
1321 if (num_modules > 0)
1322 {
1323 for (i = 0; i<num_modules && syntax_error == false; ++i)
1324 {
1325 if (LookupInModule (context, target->GetImages().GetModulePointerAtIndex(i), result, syntax_error))
1326 {
1327 result.GetOutputStream().EOL();
1328 num_successful_lookups++;
1329 }
1330 }
1331 }
1332 else
1333 {
1334 result.AppendError ("the target has no associated executable images");
1335 result.SetStatus (eReturnStatusFailed);
1336 return false;
1337 }
1338 }
1339 else
1340 {
1341 // Dump specified images (by basename or fullpath)
1342 const char *arg_cstr;
1343 for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != NULL && syntax_error == false; ++i)
1344 {
1345 FileSpec image_file(arg_cstr);
1346 ModuleList matching_modules;
1347 const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
1348
1349 if (num_matching_modules > 0)
1350 {
1351 for (size_t i=0; i<num_matching_modules; ++i)
1352 {
1353 Module * image_module = matching_modules.GetModulePointerAtIndex(i);
1354 if (image_module)
1355 {
1356 if (LookupInModule (context, image_module, result, syntax_error))
1357 {
1358 result.GetOutputStream().EOL();
1359 num_successful_lookups++;
1360 }
1361 }
1362 }
1363 }
1364 else
1365 result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
1366 }
1367 }
1368
1369 if (num_successful_lookups > 0)
1370 result.SetStatus (eReturnStatusSuccessFinishResult);
1371 else
1372 result.SetStatus (eReturnStatusFailed);
1373 }
1374 return result.Succeeded();
1375 }
1376protected:
1377
1378 CommandOptions m_options;
1379};
1380
1381lldb::OptionDefinition
1382CommandObjectImageLookup::CommandOptions::g_option_table[] =
1383{
Jim Ingham34e9a982010-06-15 18:47:14 +00001384{ LLDB_OPT_SET_1, true, "address", 'a', required_argument, NULL, 0, "<addr>", "Lookup an address in one or more executable images."},
1385{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, "<offset>", "When looking up an address subtract <offset> from any addresses before doing the lookup."},
1386{ LLDB_OPT_SET_2, true, "symbol", 's', required_argument, NULL, 0, "<name>", "Lookup a symbol by name in the symbol tables in one or more executable images."},
1387{ LLDB_OPT_SET_2, false, "regex", 'r', no_argument, NULL, 0, NULL, "The <name> argument for name lookups are regular expressions."},
1388{ LLDB_OPT_SET_3, true, "file", 'f', required_argument, NULL, 0, "<file>", "Lookup a file by fullpath or basename in one or more executable images."},
1389{ LLDB_OPT_SET_3, false, "line", 'l', required_argument, NULL, 0, "<line>", "Lookup a line number in a file (must be used in conjunction with --file)."},
1390{ LLDB_OPT_SET_3, false, "no-inlines", 'i', no_argument, NULL, 0, NULL, "Check inline line entries (must be used in conjunction with --file)."},
1391{ LLDB_OPT_SET_4, true, "function", 'n', required_argument, NULL, 0, "<name>", "Lookup a function by name in the debug symbols in one or more executable images."},
Chris Lattner24943d22010-06-08 16:52:24 +00001392{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
1393};
1394
1395
1396
1397
1398
1399//----------------------------------------------------------------------
1400// CommandObjectImage constructor
1401//----------------------------------------------------------------------
1402CommandObjectImage::CommandObjectImage(CommandInterpreter *interpreter) :
1403 CommandObjectMultiword ("image",
1404 "Access information for one or more executable images.",
1405 "image [dump|list] ...")
1406{
1407 LoadSubCommand (CommandObjectSP (new CommandObjectImageDump (interpreter)), "dump", interpreter);
1408 LoadSubCommand (CommandObjectSP (new CommandObjectImageList ()), "list", interpreter);
1409 LoadSubCommand (CommandObjectSP (new CommandObjectImageLookup ()), "lookup", interpreter);
1410}
1411
1412//----------------------------------------------------------------------
1413// Destructor
1414//----------------------------------------------------------------------
1415CommandObjectImage::~CommandObjectImage()
1416{
1417}
1418