From bb860bd2644a072b98423f7661c1e1ac10a7540c Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Tue, 9 Oct 2012 01:17:11 +0000 Subject: [PATCH] Add a parameter to Symbols::DownloadObjectAndSymbolFile() to control whether we try to call an external program to load symbols unconditionally, or if we check the user's preferences before calling it. ProcessMachCore now sets CanJIT to false - we can't execute code in a core file. DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::LoadImageUsingMemoryModule changed to load the kernel from an on-disk file if at all possible. Don't load the kext binaries out of memory from the remote systems - their linkedit doesn't seem to be in a good state and we'll error out down in SymbolVendorMacOSX if we try to use the in-memory images. Call Symbols::DownloadObjectAndSymbolFile to get the kext/kernel binary -- the external program may be able to give us a file path on the local filesystem instead of reading the binary / dSYM over a network drive every time. Fall back to calling Target::GetSharedModule() like before if DownloadObjectAndSymbolFile fails. llvm-svn: 165471 --- lldb/include/lldb/Host/Symbols.h | 8 +- lldb/source/Host/macosx/Symbols.cpp | 40 ++++++- .../Darwin-Kernel/DynamicLoaderDarwinKernel.cpp | 130 ++++++++++++--------- .../Plugins/Process/mach-core/ProcessMachCore.cpp | 2 + 4 files changed, 119 insertions(+), 61 deletions(-) diff --git a/lldb/include/lldb/Host/Symbols.h b/lldb/include/lldb/Host/Symbols.h index 30aef90..daba94b 100644 --- a/lldb/include/lldb/Host/Symbols.h +++ b/lldb/include/lldb/Host/Symbols.h @@ -52,10 +52,14 @@ public: // // Locating the file can try to download the file from a corporate build // respository, or using any other means necessary to locate both the - // unstripped object file and the debug symbols. + // unstripped object file and the debug symbols. + // The force_lookup argument controls whether the external program is called + // unconditionally to find the symbol file, or if the user's settings are + // checked to see if they've enabled the external program before calling. + // //---------------------------------------------------------------------- static bool - DownloadObjectAndSymbolFile (ModuleSpec &module_spec); + DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup = true); }; diff --git a/lldb/source/Host/macosx/Symbols.cpp b/lldb/source/Host/macosx/Symbols.cpp index 990f3ea..a8fa1c0 100644 --- a/lldb/source/Host/macosx/Symbols.cpp +++ b/lldb/source/Host/macosx/Symbols.cpp @@ -643,11 +643,41 @@ GetModuleSpecInfoFromUUIDDictionary (CFDictionaryRef uuid_dict, ModuleSpec &modu bool -Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec) +Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup) { bool success = false; const UUID *uuid_ptr = module_spec.GetUUIDPtr(); const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr(); + + // It's expensive to check for the DBGShellCommands defaults setting, only do it once per + // lldb run and cache the result. + static bool g_have_checked_for_dbgshell_command = false; + static const char *g_dbgshell_command = NULL; + if (g_have_checked_for_dbgshell_command == false) + { + g_have_checked_for_dbgshell_command = true; + CFTypeRef defaults_setting = CFPreferencesCopyAppValue (CFSTR ("DBGShellCommands"), CFSTR ("com.apple.DebugSymbols")); + if (defaults_setting && CFGetTypeID (defaults_setting) == CFStringGetTypeID()) + { + char cstr_buf[PATH_MAX]; + if (CFStringGetCString ((CFStringRef) defaults_setting, cstr_buf, sizeof (cstr_buf), kCFStringEncodingUTF8)) + { + g_dbgshell_command = strdup (cstr_buf); // this malloc'ed memory will never be freed + } + } + if (defaults_setting) + { + CFRelease (defaults_setting); + } + } + + // When g_dbgshell_command is NULL, the user has not enabled the use of an external program + // to find the symbols, don't run it for them. + if (force_lookup == false && g_dbgshell_command == NULL) + { + return false; + } + if (uuid_ptr || (file_spec_ptr && file_spec_ptr->Exists())) { static bool g_located_dsym_for_uuid_exe = false; @@ -671,9 +701,15 @@ Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec) if (!g_dsym_for_uuid_exe_exists) { dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", false); + g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); } } - + if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL) + { + dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, true); + g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); + } + if (g_dsym_for_uuid_exe_exists) dsym_for_uuid_exe_spec.GetPath (g_dsym_for_uuid_exe_path, sizeof(g_dsym_for_uuid_exe_path)); } diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp index 45834ce..a7ec411 100644 --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -14,7 +14,6 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Core/State.h" @@ -222,90 +221,107 @@ DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::LoadImageUsingMemoryModule ( { ModuleList &target_images = target.GetImages(); module_sp = target_images.FindModule(uuid); - - // Ask the Target to find this file on the local system, if possible. - // This will search in the list of currently-loaded files, look in the - // standard search paths on the system, and on a Mac it will try calling - // the DebugSymbols framework with the UUID to find the binary via its - // search methods. if (!module_sp) { ModuleSpec module_spec; module_spec.GetUUID() = uuid; module_spec.GetArchitecture() = target.GetArchitecture(); - module_sp = target.GetSharedModule (module_spec); + + // For the kernel, we really do need an on-disk file copy of the + // binary. + bool force_symbols_search = false; + if (memory_module_is_kernel) + { + force_symbols_search = true; + } + + if (Symbols::DownloadObjectAndSymbolFile (module_spec, force_symbols_search)) + { + if (module_spec.GetFileSpec().Exists()) + { + module_sp.reset(new Module (module_spec.GetFileSpec(), target.GetArchitecture())); + if (module_sp.get() && module_sp->MatchesModuleSpec (module_spec)) + { + ModuleList loaded_module_list; + loaded_module_list.Append (module_sp); + target.ModulesDidLoad (loaded_module_list); + } + } + } + + // Ask the Target to find this file on the local system, if possible. + // This will search in the list of currently-loaded files, look in the + // standard search paths on the system, and on a Mac it will try calling + // the DebugSymbols framework with the UUID to find the binary via its + // search methods. + if (!module_sp) + { + module_sp = target.GetSharedModule (module_spec); + } } } } - if (memory_module_sp) + if (memory_module_sp && module_sp) { - if (module_sp) + if (module_sp->GetUUID() == memory_module_sp->GetUUID()) { - if (module_sp->GetUUID() == memory_module_sp->GetUUID()) + target.GetImages().Append(module_sp); + if (memory_module_is_kernel && target.GetExecutableModulePointer() != module_sp.get()) + { + target.SetExecutableModule (module_sp, false); + } + + ObjectFile *ondisk_object_file = module_sp->GetObjectFile(); + ObjectFile *memory_object_file = memory_module_sp->GetObjectFile(); + if (memory_object_file && ondisk_object_file) { - ObjectFile *ondisk_object_file = module_sp->GetObjectFile(); - ObjectFile *memory_object_file = memory_module_sp->GetObjectFile(); - if (memory_object_file && ondisk_object_file) + SectionList *ondisk_section_list = ondisk_object_file->GetSectionList (); + SectionList *memory_section_list = memory_object_file->GetSectionList (); + if (memory_section_list && ondisk_section_list) { - SectionList *ondisk_section_list = ondisk_object_file->GetSectionList (); - SectionList *memory_section_list = memory_object_file->GetSectionList (); - if (memory_section_list && ondisk_section_list) + const uint32_t num_ondisk_sections = ondisk_section_list->GetSize(); + // There may be CTF sections in the memory image so we can't + // always just compare the number of sections (which are actually + // segments in mach-o parlance) + uint32_t sect_idx = 0; + + // Use the memory_module's addresses for each section to set the + // file module's load address as appropriate. We don't want to use + // a single slide value for the entire kext - different segments may + // be slid different amounts by the kext loader. + + uint32_t num_sections_loaded = 0; + for (sect_idx=0; sect_idxGetSize(); - // There may be CTF sections in the memory image so we can't - // always just compare the number of sections (which are actually - // segments in mach-o parlance) - uint32_t sect_idx = 0; - - // Use the memory_module's addresses for each section to set the - // file module's load address as appropriate. We don't want to use - // a single slide value for the entire kext - different segments may - // be slid different amounts by the kext loader. - - uint32_t num_sections_loaded = 0; - for (sect_idx=0; sect_idxGetSectionAtIndex(sect_idx)); + if (ondisk_section_sp) { - SectionSP ondisk_section_sp(ondisk_section_list->GetSectionAtIndex(sect_idx)); - if (ondisk_section_sp) + const Section *memory_section = memory_section_list->FindSectionByName(ondisk_section_sp->GetName()).get(); + if (memory_section) { - const Section *memory_section = memory_section_list->FindSectionByName(ondisk_section_sp->GetName()).get(); - if (memory_section) - { - target.GetSectionLoadList().SetSectionLoadAddress (ondisk_section_sp, memory_section->GetFileAddress()); - ++num_sections_loaded; - } + target.GetSectionLoadList().SetSectionLoadAddress (ondisk_section_sp, memory_section->GetFileAddress()); + ++num_sections_loaded; } } - if (num_sections_loaded > 0) - load_process_stop_id = process->GetStopID(); - else - module_sp.reset(); // No sections were loaded } + if (num_sections_loaded > 0) + load_process_stop_id = process->GetStopID(); else - module_sp.reset(); // One or both section lists + module_sp.reset(); // No sections were loaded } else - module_sp.reset(); // One or both object files missing + module_sp.reset(); // One or both section lists } else - module_sp.reset(); // UUID mismatch - } - - // Use the memory module as the module if we didn't find an on-disk file - // here on the debug system. - if (!module_sp) - { - module_sp = memory_module_sp; - // Load the memory image in the target as all addresses are already correct - bool changed = false; - target.GetImages().Append (memory_module_sp); - if (module_sp->SetLoadAddress (target, 0, changed)) - load_process_stop_id = process->GetStopID(); + module_sp.reset(); // One or both object files missing } + else + module_sp.reset(); // UUID mismatch } + bool is_loaded = IsLoaded(); if (so_address.IsValid()) diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp index 1e92b9e..255f46b 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -231,6 +231,8 @@ ProcessMachCore::DoLoadCore () return error; } + SetCanJIT(false); + llvm::MachO::mach_header header; DataExtractor data (&header, sizeof(header), -- 2.7.4