@@ -491,190 +491,184 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict,
491
491
return success;
492
492
}
493
493
494
- bool Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec,
495
- Status &error, bool force_lookup) {
496
- bool success = false ;
497
- const UUID *uuid_ptr = module_spec.GetUUIDPtr ();
498
- const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr ();
499
-
500
- // It's expensive to check for the DBGShellCommands defaults setting, only do
501
- // it once per lldb run and cache the result.
502
- static bool g_have_checked_for_dbgshell_command = false ;
503
- static const char *g_dbgshell_command = NULL ;
504
- if (!g_have_checked_for_dbgshell_command) {
505
- g_have_checked_for_dbgshell_command = true ;
494
+ // / It's expensive to check for the DBGShellCommands defaults setting. Only do
495
+ // / it once per lldb run and cache the result.
496
+ static llvm::StringRef GetDbgShellCommand () {
497
+ static std::once_flag g_once_flag;
498
+ static std::string g_dbgshell_command;
499
+ std::call_once (g_once_flag, [&]() {
506
500
CFTypeRef defaults_setting = CFPreferencesCopyAppValue (
507
501
CFSTR (" DBGShellCommands" ), CFSTR (" com.apple.DebugSymbols" ));
508
502
if (defaults_setting &&
509
503
CFGetTypeID (defaults_setting) == CFStringGetTypeID ()) {
510
- char cstr_buf[PATH_MAX];
511
- if (CFStringGetCString ((CFStringRef)defaults_setting, cstr_buf,
512
- sizeof (cstr_buf), kCFStringEncodingUTF8 )) {
513
- g_dbgshell_command =
514
- strdup (cstr_buf); // this malloc'ed memory will never be freed
504
+ char buffer[PATH_MAX];
505
+ if (CFStringGetCString ((CFStringRef)defaults_setting, buffer,
506
+ sizeof (buffer), kCFStringEncodingUTF8 )) {
507
+ g_dbgshell_command = buffer;
515
508
}
516
509
}
517
510
if (defaults_setting) {
518
511
CFRelease (defaults_setting);
519
512
}
513
+ });
514
+ return g_dbgshell_command;
515
+ }
516
+
517
+ // / Get the dsymForUUID executable and cache the result so we don't end up
518
+ // / stat'ing the binary over and over.
519
+ static FileSpec GetDsymForUUIDExecutable () {
520
+ // The LLDB_APPLE_DSYMFORUUID_EXECUTABLE environment variable is used by the
521
+ // test suite to override the dsymForUUID location. Because we must be able
522
+ // to change the value within a single test, don't bother caching it.
523
+ if (const char *dsymForUUID_env =
524
+ getenv (" LLDB_APPLE_DSYMFORUUID_EXECUTABLE" )) {
525
+ FileSpec dsymForUUID_executable (dsymForUUID_env);
526
+ FileSystem::Instance ().Resolve (dsymForUUID_executable);
527
+ if (FileSystem::Instance ().Exists (dsymForUUID_executable))
528
+ return dsymForUUID_executable;
520
529
}
521
530
522
- // When g_dbgshell_command is NULL, the user has not enabled the use of an
531
+ static std::once_flag g_once_flag;
532
+ static FileSpec g_dsymForUUID_executable;
533
+ std::call_once (g_once_flag, [&]() {
534
+ // Try the DBGShellCommand.
535
+ llvm::StringRef dbgshell_command = GetDbgShellCommand ();
536
+ if (!dbgshell_command.empty ()) {
537
+ g_dsymForUUID_executable = FileSpec (dbgshell_command);
538
+ FileSystem::Instance ().Resolve (g_dsymForUUID_executable);
539
+ if (FileSystem::Instance ().Exists (g_dsymForUUID_executable))
540
+ return ;
541
+ }
542
+
543
+ // Try dsymForUUID in /usr/local/bin
544
+ {
545
+ g_dsymForUUID_executable = FileSpec (" /usr/local/bin/dsymForUUID" );
546
+ if (FileSystem::Instance ().Exists (g_dsymForUUID_executable))
547
+ return ;
548
+ }
549
+
550
+ // We couldn't find the dsymForUUID binary.
551
+ g_dsymForUUID_executable = {};
552
+ });
553
+ return g_dsymForUUID_executable;
554
+ }
555
+
556
+ bool Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec,
557
+ Status &error, bool force_lookup) {
558
+ const UUID *uuid_ptr = module_spec.GetUUIDPtr ();
559
+ const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr ();
560
+
561
+ llvm::StringRef dbgshell_command = GetDbgShellCommand ();
562
+
563
+ // When dbgshell_command is empty, the user has not enabled the use of an
523
564
// external program to find the symbols, don't run it for them.
524
- if (!force_lookup && g_dbgshell_command == NULL ) {
565
+ if (!force_lookup && dbgshell_command.empty ())
566
+ return false ;
567
+
568
+ // We need a UUID or valid (existing FileSpec.
569
+ if (!uuid_ptr &&
570
+ (!file_spec_ptr || !FileSystem::Instance ().Exists (*file_spec_ptr)))
571
+ return false ;
572
+
573
+ // We need a dsymForUUID binary or an equivalent executable/script.
574
+ FileSpec dsymForUUID_exe_spec = GetDsymForUUIDExecutable ();
575
+ if (!dsymForUUID_exe_spec)
576
+ return false ;
577
+
578
+ const std::string dsymForUUID_exe_path = dsymForUUID_exe_spec.GetPath ();
579
+ const std::string uuid_str = uuid_ptr ? uuid_ptr->GetAsString () : " " ;
580
+ const std::string file_path_str =
581
+ file_spec_ptr ? file_spec_ptr->GetPath () : " " ;
582
+
583
+ Log *log = GetLog (LLDBLog::Host);
584
+
585
+ // Create the dsymForUUID command.
586
+ StreamString command;
587
+ if (!uuid_str.empty ()) {
588
+ command.Printf (" %s --ignoreNegativeCache --copyExecutable %s" ,
589
+ dsymForUUID_exe_path.c_str (), uuid_str.c_str ());
590
+ LLDB_LOGF (log, " Calling %s with UUID %s to find dSYM: %s" ,
591
+ dsymForUUID_exe_path.c_str (), uuid_str.c_str (),
592
+ command.GetString ().data ());
593
+ } else if (!file_path_str.empty ()) {
594
+ command.Printf (" %s --ignoreNegativeCache --copyExecutable %s" ,
595
+ dsymForUUID_exe_path.c_str (), file_path_str.c_str ());
596
+ LLDB_LOGF (log, " Calling %s with file %s to find dSYM: %s" ,
597
+ dsymForUUID_exe_path.c_str (), file_path_str.c_str (),
598
+ command.GetString ().data ());
599
+ } else {
525
600
return false ;
526
601
}
527
602
528
- if (uuid_ptr ||
529
- (file_spec_ptr && FileSystem::Instance ().Exists (*file_spec_ptr))) {
530
- static bool g_located_dsym_for_uuid_exe = false ;
531
- static bool g_dsym_for_uuid_exe_exists = false ;
532
- static char g_dsym_for_uuid_exe_path[PATH_MAX];
533
- if (!g_located_dsym_for_uuid_exe) {
534
- g_located_dsym_for_uuid_exe = true ;
535
- const char *dsym_for_uuid_exe_path_cstr =
536
- getenv (" LLDB_APPLE_DSYMFORUUID_EXECUTABLE" );
537
- FileSpec dsym_for_uuid_exe_spec;
538
- if (dsym_for_uuid_exe_path_cstr) {
539
- dsym_for_uuid_exe_spec.SetFile (dsym_for_uuid_exe_path_cstr,
540
- FileSpec::Style::native);
541
- FileSystem::Instance ().Resolve (dsym_for_uuid_exe_spec);
542
- g_dsym_for_uuid_exe_exists =
543
- FileSystem::Instance ().Exists (dsym_for_uuid_exe_spec);
544
- }
603
+ // Invoke dsymForUUID.
604
+ int exit_status = -1 ;
605
+ int signo = -1 ;
606
+ std::string command_output;
607
+ error = Host::RunShellCommand (
608
+ command.GetData (),
609
+ FileSpec (), // current working directory
610
+ &exit_status, // Exit status
611
+ &signo, // Signal int *
612
+ &command_output, // Command output
613
+ std::chrono::seconds (
614
+ 640 ), // Large timeout to allow for long dsym download times
615
+ false ); // Don't run in a shell (we don't need shell expansion)
616
+
617
+ if (error.Fail () || exit_status != 0 || command_output.empty ()) {
618
+ LLDB_LOGF (log, " '%s' failed (exit status: %d, error: '%s', output: '%s')" ,
619
+ command.GetData (), exit_status, error.AsCString (),
620
+ command_output.c_str ());
621
+ return false ;
622
+ }
545
623
546
- if (!g_dsym_for_uuid_exe_exists) {
547
- dsym_for_uuid_exe_spec.SetFile (" /usr/local/bin/dsymForUUID" ,
548
- FileSpec::Style::native);
549
- g_dsym_for_uuid_exe_exists =
550
- FileSystem::Instance ().Exists (dsym_for_uuid_exe_spec);
551
- if (!g_dsym_for_uuid_exe_exists) {
552
- long bufsize;
553
- if ((bufsize = sysconf (_SC_GETPW_R_SIZE_MAX)) != -1 ) {
554
- char buffer[bufsize];
555
- struct passwd pwd;
556
- struct passwd *tilde_rc = NULL ;
557
- // we are a library so we need to use the reentrant version of
558
- // getpwnam()
559
- if (getpwnam_r (" rc" , &pwd, buffer, bufsize, &tilde_rc) == 0 &&
560
- tilde_rc && tilde_rc->pw_dir ) {
561
- std::string dsymforuuid_path (tilde_rc->pw_dir );
562
- dsymforuuid_path += " /bin/dsymForUUID" ;
563
- dsym_for_uuid_exe_spec.SetFile (dsymforuuid_path.c_str (),
564
- FileSpec::Style::native);
565
- g_dsym_for_uuid_exe_exists =
566
- FileSystem::Instance ().Exists (dsym_for_uuid_exe_spec);
567
- }
568
- }
569
- }
570
- }
571
- if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL ) {
572
- dsym_for_uuid_exe_spec.SetFile (g_dbgshell_command,
573
- FileSpec::Style::native);
574
- FileSystem::Instance ().Resolve (dsym_for_uuid_exe_spec);
575
- g_dsym_for_uuid_exe_exists =
576
- FileSystem::Instance ().Exists (dsym_for_uuid_exe_spec);
577
- }
624
+ CFCData data (
625
+ CFDataCreateWithBytesNoCopy (NULL , (const UInt8 *)command_output.data (),
626
+ command_output.size (), kCFAllocatorNull ));
627
+
628
+ CFCReleaser<CFDictionaryRef> plist (
629
+ (CFDictionaryRef)::CFPropertyListCreateFromXMLData (
630
+ NULL , data.get (), kCFPropertyListImmutable , NULL ));
631
+
632
+ if (!plist.get ()) {
633
+ LLDB_LOGF (log, " '%s' failed: output is not a valid plist" ,
634
+ command.GetData ());
635
+ return false ;
636
+ }
637
+
638
+ if (CFGetTypeID (plist.get ()) != CFDictionaryGetTypeID ()) {
639
+ LLDB_LOGF (log, " '%s' failed: output plist is not a valid CFDictionary" ,
640
+ command.GetData ());
641
+ return false ;
642
+ }
578
643
579
- if (g_dsym_for_uuid_exe_exists)
580
- dsym_for_uuid_exe_spec.GetPath (g_dsym_for_uuid_exe_path,
581
- sizeof (g_dsym_for_uuid_exe_path));
644
+ if (!uuid_str.empty ()) {
645
+ CFCString uuid_cfstr (uuid_str.c_str ());
646
+ CFDictionaryRef uuid_dict =
647
+ (CFDictionaryRef)CFDictionaryGetValue (plist.get (), uuid_cfstr.get ());
648
+ return GetModuleSpecInfoFromUUIDDictionary (uuid_dict, module_spec, error);
649
+ }
650
+
651
+ if (const CFIndex num_values = ::CFDictionaryGetCount (plist.get ())) {
652
+ std::vector<CFStringRef> keys (num_values, NULL );
653
+ std::vector<CFDictionaryRef> values (num_values, NULL );
654
+ ::CFDictionaryGetKeysAndValues (plist.get(), NULL,
655
+ (const void **)&values[0]);
656
+ if (num_values == 1 ) {
657
+ return GetModuleSpecInfoFromUUIDDictionary (values[0 ], module_spec, error);
582
658
}
583
- if (g_dsym_for_uuid_exe_exists) {
584
- std::string uuid_str;
585
- char file_path[PATH_MAX];
586
- file_path[0 ] = ' \0 ' ;
587
-
588
- if (uuid_ptr)
589
- uuid_str = uuid_ptr->GetAsString ();
590
-
591
- if (file_spec_ptr)
592
- file_spec_ptr->GetPath (file_path, sizeof (file_path));
593
-
594
- StreamString command;
595
- if (!uuid_str.empty ())
596
- command.Printf (" %s --ignoreNegativeCache --copyExecutable %s" ,
597
- g_dsym_for_uuid_exe_path, uuid_str.c_str ());
598
- else if (file_path[0 ] != ' \0 ' )
599
- command.Printf (" %s --ignoreNegativeCache --copyExecutable %s" ,
600
- g_dsym_for_uuid_exe_path, file_path);
601
-
602
- if (!command.GetString ().empty ()) {
603
- Log *log = GetLog (LLDBLog::Host);
604
- int exit_status = -1 ;
605
- int signo = -1 ;
606
- std::string command_output;
607
- if (log) {
608
- if (!uuid_str.empty ())
609
- LLDB_LOGF (log, " Calling %s with UUID %s to find dSYM" ,
610
- g_dsym_for_uuid_exe_path, uuid_str.c_str ());
611
- else if (file_path[0 ] != ' \0 ' )
612
- LLDB_LOGF (log, " Calling %s with file %s to find dSYM" ,
613
- g_dsym_for_uuid_exe_path, file_path);
614
- }
615
- error = Host::RunShellCommand (
616
- command.GetData (),
617
- FileSpec (), // current working directory
618
- &exit_status, // Exit status
619
- &signo, // Signal int *
620
- &command_output, // Command output
621
- std::chrono::seconds (
622
- 640 ), // Large timeout to allow for long dsym download times
623
- false ); // Don't run in a shell (we don't need shell expansion)
624
- if (error.Success () && exit_status == 0 && !command_output.empty ()) {
625
- CFCData data (CFDataCreateWithBytesNoCopy (
626
- NULL , (const UInt8 *)command_output.data (), command_output.size (),
627
- kCFAllocatorNull ));
628
-
629
- CFCReleaser<CFDictionaryRef> plist (
630
- (CFDictionaryRef)::CFPropertyListCreateFromXMLData (
631
- NULL , data.get (), kCFPropertyListImmutable , NULL ));
632
-
633
- if (plist.get () &&
634
- CFGetTypeID (plist.get ()) == CFDictionaryGetTypeID ()) {
635
- if (!uuid_str.empty ()) {
636
- CFCString uuid_cfstr (uuid_str.c_str ());
637
- CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue (
638
- plist.get (), uuid_cfstr.get ());
639
- success = GetModuleSpecInfoFromUUIDDictionary (uuid_dict,
640
- module_spec, error);
641
- } else {
642
- const CFIndex num_values = ::CFDictionaryGetCount (plist.get ());
643
- if (num_values > 0 ) {
644
- std::vector<CFStringRef> keys (num_values, NULL );
645
- std::vector<CFDictionaryRef> values (num_values, NULL );
646
- ::CFDictionaryGetKeysAndValues (plist.get(), NULL,
647
- (const void **)&values[0]);
648
- if (num_values == 1 ) {
649
- success = GetModuleSpecInfoFromUUIDDictionary (
650
- values[0 ], module_spec, error);
651
- return success;
652
- } else {
653
- for (CFIndex i = 0 ; i < num_values; ++i) {
654
- ModuleSpec curr_module_spec;
655
- if (GetModuleSpecInfoFromUUIDDictionary (
656
- values[i], curr_module_spec, error)) {
657
- if (module_spec.GetArchitecture ().IsCompatibleMatch (
658
- curr_module_spec.GetArchitecture ())) {
659
- module_spec = curr_module_spec;
660
- return true ;
661
- }
662
- }
663
- }
664
- }
665
- }
666
- }
667
- }
668
- } else {
669
- if (!uuid_str.empty ())
670
- LLDB_LOGF (log, " Called %s on %s, no matches" ,
671
- g_dsym_for_uuid_exe_path, uuid_str.c_str ());
672
- else if (file_path[0 ] != ' \0 ' )
673
- LLDB_LOGF (log, " Called %s on %s, no matches" ,
674
- g_dsym_for_uuid_exe_path, file_path);
659
+
660
+ for (CFIndex i = 0 ; i < num_values; ++i) {
661
+ ModuleSpec curr_module_spec;
662
+ if (GetModuleSpecInfoFromUUIDDictionary (values[i], curr_module_spec,
663
+ error)) {
664
+ if (module_spec.GetArchitecture ().IsCompatibleMatch (
665
+ curr_module_spec.GetArchitecture ())) {
666
+ module_spec = curr_module_spec;
667
+ return true ;
675
668
}
676
669
}
677
670
}
678
671
}
679
- return success;
672
+
673
+ return false ;
680
674
}
0 commit comments