52
52
#include " lldb/Utility/FileSpec.h"
53
53
#include " lldb/Utility/LLDBLog.h"
54
54
#include " lldb/Utility/State.h"
55
+ #include " lldb/Utility/StructuredData.h"
55
56
#include " lldb/Utility/Timer.h"
56
57
#include " lldb/lldb-enumerations.h"
57
58
#include " lldb/lldb-private-enumerations.h"
61
62
#include " clang/Frontend/CompilerInvocation.h"
62
63
#include " clang/Frontend/FrontendActions.h"
63
64
#include " llvm/ADT/ScopeExit.h"
65
+ #include " llvm/ADT/StringRef.h"
64
66
#include " llvm/Support/FileSystem.h"
65
67
#include " llvm/Support/FormatAdapters.h"
66
68
@@ -1462,6 +1464,87 @@ static bool DumpModuleSymbolFile(Stream &strm, Module *module) {
1462
1464
return false ;
1463
1465
}
1464
1466
1467
+ static bool GetSeparateDebugInfoList (StructuredData::Array &list,
1468
+ Module *module ) {
1469
+ if (module ) {
1470
+ if (SymbolFile *symbol_file = module ->GetSymbolFile (/* can_create=*/ true )) {
1471
+ StructuredData::Dictionary d;
1472
+ if (symbol_file->GetSeparateDebugInfo (d)) {
1473
+ list.AddItem (
1474
+ std::make_shared<StructuredData::Dictionary>(std::move (d)));
1475
+ return true ;
1476
+ }
1477
+ }
1478
+ }
1479
+ return false ;
1480
+ }
1481
+
1482
+ static void DumpDwoFilesTable (Stream &strm,
1483
+ StructuredData::Array &dwo_listings) {
1484
+ strm.PutCString (" Dwo ID Err Dwo Path" );
1485
+ strm.EOL ();
1486
+ strm.PutCString (
1487
+ " ------------------ --- -----------------------------------------" );
1488
+ strm.EOL ();
1489
+ dwo_listings.ForEach ([&strm](StructuredData::Object *dwo) {
1490
+ StructuredData::Dictionary *dict = dwo->GetAsDictionary ();
1491
+ if (!dict)
1492
+ return false ;
1493
+
1494
+ uint64_t dwo_id;
1495
+ if (dict->GetValueForKeyAsInteger (" dwo_id" , dwo_id))
1496
+ strm.Printf (" 0x%16.16" PRIx64 " " , dwo_id);
1497
+ else
1498
+ strm.Printf (" 0x???????????????? " );
1499
+
1500
+ llvm::StringRef error;
1501
+ if (dict->GetValueForKeyAsString (" error" , error))
1502
+ strm << " E " << error;
1503
+ else {
1504
+ llvm::StringRef resolved_dwo_path;
1505
+ if (dict->GetValueForKeyAsString (" resolved_dwo_path" ,
1506
+ resolved_dwo_path)) {
1507
+ strm << " " << resolved_dwo_path;
1508
+ if (resolved_dwo_path.ends_with (" .dwp" )) {
1509
+ llvm::StringRef dwo_name;
1510
+ if (dict->GetValueForKeyAsString (" dwo_name" , dwo_name))
1511
+ strm << " (" << dwo_name << " )" ;
1512
+ }
1513
+ }
1514
+ }
1515
+ strm.EOL ();
1516
+ return true ;
1517
+ });
1518
+ }
1519
+
1520
+ static void DumpOsoFilesTable (Stream &strm,
1521
+ StructuredData::Array &oso_listings) {
1522
+ strm.PutCString (" Mod Time Err Oso Path" );
1523
+ strm.EOL ();
1524
+ strm.PutCString (" ------------------ --- ---------------------" );
1525
+ strm.EOL ();
1526
+ oso_listings.ForEach ([&strm](StructuredData::Object *oso) {
1527
+ StructuredData::Dictionary *dict = oso->GetAsDictionary ();
1528
+ if (!dict)
1529
+ return false ;
1530
+
1531
+ uint32_t oso_mod_time;
1532
+ if (dict->GetValueForKeyAsInteger (" oso_mod_time" , oso_mod_time))
1533
+ strm.Printf (" 0x%16.16" PRIx32 " " , oso_mod_time);
1534
+
1535
+ llvm::StringRef error;
1536
+ if (dict->GetValueForKeyAsString (" error" , error))
1537
+ strm << " E " << error;
1538
+ else {
1539
+ llvm::StringRef oso_path;
1540
+ if (dict->GetValueForKeyAsString (" oso_path" , oso_path))
1541
+ strm << " " << oso_path;
1542
+ }
1543
+ strm.EOL ();
1544
+ return true ;
1545
+ });
1546
+ }
1547
+
1465
1548
static void DumpAddress (ExecutionContextScope *exe_scope,
1466
1549
const Address &so_addr, bool verbose, bool all_ranges,
1467
1550
Stream &strm) {
@@ -2462,6 +2545,176 @@ class CommandObjectTargetModulesDumpLineTable
2462
2545
CommandOptions m_options;
2463
2546
};
2464
2547
2548
+ #pragma mark CommandObjectTargetModulesDumpSeparateDebugInfoFiles
2549
+ #define LLDB_OPTIONS_target_modules_dump_separate_debug_info
2550
+ #include " CommandOptions.inc"
2551
+
2552
+ // Image debug separate debug info dumping command
2553
+
2554
+ class CommandObjectTargetModulesDumpSeparateDebugInfoFiles
2555
+ : public CommandObjectTargetModulesModuleAutoComplete {
2556
+ public:
2557
+ CommandObjectTargetModulesDumpSeparateDebugInfoFiles (
2558
+ CommandInterpreter &interpreter)
2559
+ : CommandObjectTargetModulesModuleAutoComplete(
2560
+ interpreter, " target modules dump separate-debug-info" ,
2561
+ " List the separate debug info symbol files for one or more target "
2562
+ " modules." ,
2563
+ nullptr , eCommandRequiresTarget) {}
2564
+
2565
+ ~CommandObjectTargetModulesDumpSeparateDebugInfoFiles () override = default ;
2566
+
2567
+ Options *GetOptions () override { return &m_options; }
2568
+
2569
+ class CommandOptions : public Options {
2570
+ public:
2571
+ CommandOptions () = default ;
2572
+
2573
+ ~CommandOptions () override = default ;
2574
+
2575
+ Status SetOptionValue (uint32_t option_idx, llvm::StringRef option_arg,
2576
+ ExecutionContext *execution_context) override {
2577
+ Status error;
2578
+ const int short_option = m_getopt_table[option_idx].val ;
2579
+
2580
+ switch (short_option) {
2581
+ case ' j' :
2582
+ m_json.SetCurrentValue (true );
2583
+ m_json.SetOptionWasSet ();
2584
+ break ;
2585
+
2586
+ default :
2587
+ llvm_unreachable (" Unimplemented option" );
2588
+ }
2589
+ return error;
2590
+ }
2591
+
2592
+ void OptionParsingStarting (ExecutionContext *execution_context) override {
2593
+ m_json.Clear ();
2594
+ }
2595
+
2596
+ llvm::ArrayRef<OptionDefinition> GetDefinitions () override {
2597
+ return llvm::ArrayRef (g_target_modules_dump_separate_debug_info_options);
2598
+ }
2599
+
2600
+ OptionValueBoolean m_json = false ;
2601
+ };
2602
+
2603
+ protected:
2604
+ bool DoExecute (Args &command, CommandReturnObject &result) override {
2605
+ Target &target = GetSelectedTarget ();
2606
+ uint32_t num_dumped = 0 ;
2607
+
2608
+ uint32_t addr_byte_size = target.GetArchitecture ().GetAddressByteSize ();
2609
+ result.GetOutputStream ().SetAddressByteSize (addr_byte_size);
2610
+ result.GetErrorStream ().SetAddressByteSize (addr_byte_size);
2611
+
2612
+ StructuredData::Array separate_debug_info_lists_by_module;
2613
+ if (command.GetArgumentCount () == 0 ) {
2614
+ // Dump all sections for all modules images
2615
+ const ModuleList &target_modules = target.GetImages ();
2616
+ std::lock_guard<std::recursive_mutex> guard (target_modules.GetMutex ());
2617
+ const size_t num_modules = target_modules.GetSize ();
2618
+ if (num_modules == 0 ) {
2619
+ result.AppendError (" the target has no associated executable images" );
2620
+ return false ;
2621
+ }
2622
+ for (ModuleSP module_sp : target_modules.ModulesNoLocking ()) {
2623
+ if (INTERRUPT_REQUESTED (
2624
+ GetDebugger (),
2625
+ " Interrupted in dumping all "
2626
+ " separate debug info with {0} of {1} modules dumped" ,
2627
+ num_dumped, num_modules))
2628
+ break ;
2629
+
2630
+ if (GetSeparateDebugInfoList (separate_debug_info_lists_by_module,
2631
+ module_sp.get ()))
2632
+ num_dumped++;
2633
+ }
2634
+ } else {
2635
+ // Dump specified images (by basename or fullpath)
2636
+ const char *arg_cstr;
2637
+ for (int arg_idx = 0 ;
2638
+ (arg_cstr = command.GetArgumentAtIndex (arg_idx)) != nullptr ;
2639
+ ++arg_idx) {
2640
+ ModuleList module_list;
2641
+ const size_t num_matches =
2642
+ FindModulesByName (&target, arg_cstr, module_list, true );
2643
+ if (num_matches > 0 ) {
2644
+ for (size_t i = 0 ; i < num_matches; ++i) {
2645
+ if (INTERRUPT_REQUESTED (GetDebugger (),
2646
+ " Interrupted dumping {0} "
2647
+ " of {1} requested modules" ,
2648
+ i, num_matches))
2649
+ break ;
2650
+ Module *module = module_list.GetModulePointerAtIndex (i);
2651
+ if (GetSeparateDebugInfoList (separate_debug_info_lists_by_module,
2652
+ module ))
2653
+ num_dumped++;
2654
+ }
2655
+ } else
2656
+ result.AppendWarningWithFormat (
2657
+ " Unable to find an image that matches '%s'.\n " , arg_cstr);
2658
+ }
2659
+ }
2660
+
2661
+ if (num_dumped > 0 ) {
2662
+ Stream &strm = result.GetOutputStream ();
2663
+ if (m_options.m_json ) {
2664
+ separate_debug_info_lists_by_module.Dump (strm,
2665
+ /* pretty_print=*/ true );
2666
+ } else {
2667
+ // List the debug info files in human readable form.
2668
+ separate_debug_info_lists_by_module.ForEach (
2669
+ [&result, &strm](StructuredData::Object *obj) {
2670
+ if (!obj) {
2671
+ return false ;
2672
+ }
2673
+
2674
+ // Each item in `separate_debug_info_lists_by_module` should be a
2675
+ // valid structured data dictionary.
2676
+ StructuredData::Dictionary *separate_debug_info_list =
2677
+ obj->GetAsDictionary ();
2678
+ if (!separate_debug_info_list) {
2679
+ return false ;
2680
+ }
2681
+
2682
+ llvm::StringRef type;
2683
+ llvm::StringRef symfile;
2684
+ StructuredData::Array *files;
2685
+ assert (separate_debug_info_list->GetValueForKeyAsString (" type" ,
2686
+ type));
2687
+ assert (separate_debug_info_list->GetValueForKeyAsString (" symfile" ,
2688
+ symfile));
2689
+ assert (separate_debug_info_list->GetValueForKeyAsArray (
2690
+ " separate-debug-info-files" , files));
2691
+
2692
+ strm << " Symbol file: " << symfile;
2693
+ strm.EOL ();
2694
+ strm << " Type: \" " << type << " \" " ;
2695
+ strm.EOL ();
2696
+ if (type == " dwo" ) {
2697
+ DumpDwoFilesTable (strm, *files);
2698
+ } else if (type == " oso" ) {
2699
+ DumpOsoFilesTable (strm, *files);
2700
+ } else {
2701
+ result.AppendWarningWithFormat (
2702
+ " Found unsupported debug info type '%s'.\n " ,
2703
+ type.str ().c_str ());
2704
+ }
2705
+ return true ;
2706
+ });
2707
+ }
2708
+ result.SetStatus (eReturnStatusSuccessFinishResult);
2709
+ } else {
2710
+ result.AppendError (" no matching executable images found" );
2711
+ }
2712
+ return result.Succeeded ();
2713
+ }
2714
+
2715
+ CommandOptions m_options;
2716
+ };
2717
+
2465
2718
#pragma mark CommandObjectTargetModulesDump
2466
2719
2467
2720
// Dump multi-word command for target modules
@@ -2475,7 +2728,8 @@ class CommandObjectTargetModulesDump : public CommandObjectMultiword {
2475
2728
" Commands for dumping information about one or more target "
2476
2729
" modules." ,
2477
2730
" target modules dump "
2478
- " [objfile|symtab|sections|ast|symfile|line-table|pcm-info] "
2731
+ " [objfile|symtab|sections|ast|symfile|line-table|pcm-info|separate-"
2732
+ " debug-info] "
2479
2733
" [<file1> <file2> ...]" ) {
2480
2734
LoadSubCommand (" objfile" ,
2481
2735
CommandObjectSP (
@@ -2499,6 +2753,10 @@ class CommandObjectTargetModulesDump : public CommandObjectMultiword {
2499
2753
" pcm-info" ,
2500
2754
CommandObjectSP (
2501
2755
new CommandObjectTargetModulesDumpClangPCMInfo (interpreter)));
2756
+ LoadSubCommand (" separate-debug-info" ,
2757
+ CommandObjectSP (
2758
+ new CommandObjectTargetModulesDumpSeparateDebugInfoFiles (
2759
+ interpreter)));
2502
2760
}
2503
2761
2504
2762
~CommandObjectTargetModulesDump () override = default ;
0 commit comments