diff options
-rw-r--r-- | lldb/include/lldb/Target/DynamicLoader.h | 2 | ||||
-rw-r--r-- | lldb/lldb.xcodeproj/project.pbxproj | 6 | ||||
-rw-r--r-- | lldb/source/Expression/ClangUserExpression.cpp | 4 | ||||
-rw-r--r-- | lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp | 521 | ||||
-rw-r--r-- | lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h | 42 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Target/Process.cpp | 3 | ||||
-rw-r--r-- | lldb/test/types/AbstractBase.py | 21 | ||||
-rw-r--r-- | lldb/test/types/basic_type.cpp | 2 |
9 files changed, 393 insertions, 210 deletions
diff --git a/lldb/include/lldb/Target/DynamicLoader.h b/lldb/include/lldb/Target/DynamicLoader.h index af125677274..0dc85920f31 100644 --- a/lldb/include/lldb/Target/DynamicLoader.h +++ b/lldb/include/lldb/Target/DynamicLoader.h @@ -91,6 +91,8 @@ public: //------------------------------------------------------------------ virtual void DidLaunch () = 0; + + //------------------------------------------------------------------ /// Get whether the process should stop when images change. diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 10e11c9c21b..18918f2db5d 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -3292,7 +3292,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -3324,7 +3324,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PREPROCESSOR_DEFINITIONS = ( __STDC_CONSTANT_MACROS, @@ -3616,7 +3616,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PREPROCESSOR_DEFINITIONS = ( __STDC_CONSTANT_MACROS, diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp index 119b142e058..3c8c3434293 100644 --- a/lldb/source/Expression/ClangUserExpression.cpp +++ b/lldb/source/Expression/ClangUserExpression.cpp @@ -597,9 +597,9 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, Error error; ExecutionResults execution_results = eExecutionSetupError; - if (exe_ctx.process == NULL) + if (exe_ctx.process == NULL || exe_ctx.process->GetState() != lldb::eStateStopped) { - error.SetErrorString ("Must have a process to evaluate expressions."); + error.SetErrorString ("Must have a live but stopped process to evaluate expressions."); result_valobj_sp = ValueObjectConstResult::Create (NULL, error); return eExecutionSetupError; diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp index c9f6e3281a8..5322f1f6ef6 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp @@ -288,7 +288,7 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb:: } // Update all image infos - UpdateAllImageInfos(); + InitializeFromAllImageInfos (); // If we didn't have an executable before, but now we do, then the // dyld module shared pointer might be unique and we may need to add @@ -442,11 +442,79 @@ DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, DYLDImageInfo& // or not (based on global preference). //---------------------------------------------------------------------- bool -DynamicLoaderMacOSXDYLD::NotifyBreakpointHit (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id) +DynamicLoaderMacOSXDYLD::NotifyBreakpointHit (void *baton, + StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id) { // Let the event know that the images have changed + // DYLD passes three arguments to the notification breakpoint. + // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing + // Arg2: uint32_t infoCount - Number of shared libraries added + // Arg3: dyld_image_info info[] - Array of structs of the form: + // const struct mach_header *imageLoadAddress + // const char *imageFilePath + // uintptr_t imageFileModDate (a time_t) + DynamicLoaderMacOSXDYLD* dyld_instance = (DynamicLoaderMacOSXDYLD*) baton; - dyld_instance->UpdateAllImageInfos(); + + // First step is to see if we've already initialized the all image infos. If we haven't then this function + // will do so and return true. In the course of initializing the all_image_infos it will read the complete + // current state, so we don't need to figure out what has changed from the data passed in to us. + + if (dyld_instance->InitializeFromAllImageInfos()) + return dyld_instance->GetStopWhenImagesChange(); + + Process *process = context->exe_ctx.process; + const lldb::ABISP &abi = process->GetABI(); + if (abi != NULL) + { + // Build up the value array to store the three arguments given above, then get the values from the ABI: + + ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); + ValueList argument_values; + Value input_value; + + void *clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false); + void *clang_uint32_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 32); + input_value.SetValueType (Value::eValueTypeScalar); + input_value.SetContext (Value::eContextTypeClangType, clang_uint32_type); + argument_values.PushValue(input_value); + argument_values.PushValue(input_value); + input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type); + argument_values.PushValue (input_value); + + if (abi->GetArgumentValues (*context->exe_ctx.thread, argument_values)) + { + uint32_t dyld_mode = argument_values.GetValueAtIndex(0)->GetScalar().UInt (-1); + if (dyld_mode != -1) + { + // Okay the mode was right, now get the number of elements, and the array of new elements... + uint32_t image_infos_count = argument_values.GetValueAtIndex(1)->GetScalar().UInt (-1); + if (image_infos_count != -1) + { + // Got the number added, now go through the array of added elements, putting out the mach header + // address, and adding the image. + // Note, I'm not putting in logging here, since the AddModules & RemoveModules functions do + // all the logging internally. + + lldb::addr_t image_infos_addr = argument_values.GetValueAtIndex(2)->GetScalar().ULongLong(); + if (dyld_mode == 0) + { + // This is add: + dyld_instance->AddModulesUsingImageInfosAddress (image_infos_addr, image_infos_count); + } + else + { + // This is remove: + dyld_instance->RemoveModulesUsingImageInfosAddress (image_infos_addr, image_infos_count); + } + + } + } + } + } + // Return true to stop the target, false to just let the target run return dyld_instance->GetStopWhenImagesChange(); } @@ -571,229 +639,297 @@ DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure () return false; } -//---------------------------------------------------------------------- -// If we have found where the "_dyld_all_image_infos" lives in memory, -// read the current info from it, and then update all image load -// addresses (or lack thereof). -//---------------------------------------------------------------------- -uint32_t -DynamicLoaderMacOSXDYLD::UpdateAllImageInfos() + +bool +DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count) { + DYLDImageInfo::collection image_infos; LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); - ModuleList& target_images = m_process->GetTarget().GetImages(); + if (log) + log->Printf ("Adding %d modules.\n"); + + Mutex::Locker locker(m_mutex); + if (m_process->GetStopID() == m_dyld_image_infos_stop_id) + return true; - if (ReadAllImageInfosStructure ()) - { - Mutex::Locker locker(m_mutex); - if (m_process->GetStopID() == m_dyld_image_infos_stop_id) - m_dyld_image_infos.size(); + if (!ReadImageInfos (image_infos_addr, image_infos_count, image_infos)) + return false; + + UpdateImageInfosHeaderAndLoadCommands (image_infos, image_infos_count, false); + bool return_value = AddModulesUsingImageInfos (image_infos); + m_dyld_image_infos_stop_id = m_process->GetStopID(); + return return_value; +} - uint32_t idx; - uint32_t i = 0; - // Since we can't downsize a vector, we must do this using the swap method - DYLDImageInfo::collection old_dyld_all_image_infos; - old_dyld_all_image_infos.swap(m_dyld_image_infos); +// Adds the modules in image_infos to m_dyld_image_infos. +// NB don't call this passing in m_dyld_image_infos. - // If we made it here, we are assuming that the all dylib info data should - // be valid, lets read the info array. - const ByteOrder endian = m_dyld.GetByteOrder(); - const uint32_t addr_size = m_dyld.GetAddressByteSize(); +bool +DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos) +{ + // Now add these images to the main list. + ModuleList loaded_module_list; + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + + for (uint32_t idx = 0; idx < image_infos.size(); ++idx) + { + if (log) + { + log->Printf ("Adding new image at address=0x%16.16llx.", image_infos[idx].address); + image_infos[idx].PutToLog (log.get()); + } + + m_dyld_image_infos.push_back(image_infos[idx]); + + ModuleSP image_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[idx], true, NULL)); - if (m_dyld_all_image_infos.dylib_info_count > 0) + if (image_module_sp) { - if (m_dyld_all_image_infos.dylib_info_addr == 0) - { - // DYLD is updating the images right now... - } - else + if (image_infos[idx].header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor) + image_module_sp->SetIsDynamicLinkEditor (true); + + ObjectFile *objfile = image_module_sp->GetObjectFile (); + if (objfile) { - m_dyld_image_infos.resize(m_dyld_all_image_infos.dylib_info_count); - const size_t count = m_dyld_image_infos.size() * 3 * addr_size; - DataBufferHeap info_data(count, 0); - Error error; - const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos.dylib_info_addr, - info_data.GetBytes(), - info_data.GetByteSize(), - error); - if (bytes_read == count) + SectionList *sections = objfile->GetSectionList(); + if (sections) { - uint32_t info_data_offset = 0; - DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size); - for (i = 0; i < m_dyld_image_infos.size() && info_data_ref.ValidOffset(info_data_offset); i++) + ConstString commpage_dbstr("__commpage"); + Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get(); + if (commpage_section) { - m_dyld_image_infos[i].address = info_data_ref.GetPointer(&info_data_offset); - lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset); - m_dyld_image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset); - - char raw_path[PATH_MAX]; - m_process->ReadCStringFromMemory (path_addr, raw_path, sizeof(raw_path)); - // don't resolve the path - const bool resolve_path = false; - m_dyld_image_infos[i].file_spec.SetFile(raw_path, resolve_path); + ModuleList& target_images = m_process->GetTarget().GetImages(); + const FileSpec objfile_file_spec = objfile->GetFileSpec(); + ArchSpec arch (image_infos[idx].GetArchitecture ()); + ModuleSP commpage_image_module_sp(target_images.FindFirstModuleForFileSpec (objfile_file_spec, + &arch, + &commpage_dbstr)); + if (!commpage_image_module_sp) + { + commpage_image_module_sp + = m_process->GetTarget().GetSharedModule (image_infos[idx].file_spec, + arch, + NULL, + &commpage_dbstr, + objfile->GetOffset() + commpage_section->GetFileOffset()); + } + if (commpage_image_module_sp) + UpdateCommPageLoadAddress (commpage_image_module_sp.get()); } - - UpdateAllImageInfosHeaderAndLoadCommands(); - } - else - { - DEBUG_PRINTF( "unable to read all data for all_dylib_infos."); - m_dyld_image_infos.clear(); } } - } - // If our new list is smaller than our old list, we have unloaded - // some shared libraries - if (m_dyld_image_infos.size() != old_dyld_all_image_infos.size()) + // UpdateImageLoadAddress will return true if any segments + // change load address. We need to check this so we don't + // mention that all loaded shared libraries are newly loaded + // each time we hit out dyld breakpoint since dyld will list all + // shared libraries each time. + if (UpdateImageLoadAddress (image_module_sp.get(), image_infos[idx])) + { + loaded_module_list.AppendIfNeeded (image_module_sp); + } + } + } + + if (loaded_module_list.GetSize() > 0) + { + // FIXME: This should really be in the Runtime handlers class, which should get + // called by the target's ModulesDidLoad, but we're doing it all locally for now + // to save time. + // Also, I'm assuming there can be only one libobjc dylib loaded... + + ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime(); + if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary()) { - ModuleList unloaded_module_list; - if (old_dyld_all_image_infos.size() == 0) + size_t num_modules = loaded_module_list.GetSize(); + for (int i = 0; i < num_modules; i++) { - // This is the first time we are loading shared libraries, - // we need to make sure to trim anything that isn't in the - // m_dyld_image_infos out of the target module list since - // we might have shared libraries that got loaded from - // elsewhere due to DYLD_FRAMEWORK_PATH, or DYLD_LIBRARY_PATH - // environment variables... - const size_t num_images = target_images.GetSize(); - for (idx = 0; idx < num_images; ++idx) + if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i))) { - ModuleSP module_sp (target_images.GetModuleAtIndex (idx)); - - if (GetImageInfo (module_sp.get()) == NULL) - unloaded_module_list.AppendIfNeeded (module_sp); + objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i)); + break; } } - else + } + if (log) + loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidLoad"); + m_process->GetTarget().ModulesDidLoad (loaded_module_list); + } + return true; +} + +bool +DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count) +{ + DYLDImageInfo::collection image_infos; + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + + Mutex::Locker locker(m_mutex); + if (m_process->GetStopID() == m_dyld_image_infos_stop_id) + return true; + + // First read in the image_infos for the removed modules, and their headers & load commands. + if (!ReadImageInfos (image_infos_addr, image_infos_count, image_infos)) + { + if (log) + log->PutCString ("Failed reading image infos array."); + return false; + } + + if (log) + log->Printf ("Removing %d modules.", image_infos_count); + + ModuleList unloaded_module_list; + for (uint32_t idx = 0; idx < image_infos.size(); ++idx) + { + if (log) + { + log->Printf ("Removing module at address=0x%16.16llx.", image_infos[idx].address); + image_infos[idx].PutToLog (log.get()); + } + + // Remove this image_infos from the m_all_image_infos. We do the comparision by address + // rather than by file spec because we can have many modules with the same "file spec" in the + // case that they are modules loaded from memory. + // + // Also copy over the uuid from the old entry to the removed entry so we can + // use it to lookup the module in the module list. + + DYLDImageInfo::collection::iterator pos, end = m_dyld_image_infos.end(); + for (pos = m_dyld_image_infos.begin(); pos != end; pos++) + { + if (image_infos[idx].address == (*pos).address) { - uint32_t old_idx; - for (idx = 0; idx < old_dyld_all_image_infos.size(); ++idx) + image_infos[idx].uuid = (*pos).uuid; + + // Add the module from this image_info to the "unloaded_module_list". We'll remove them all at + // one go later on. + + ModuleSP unload_image_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[idx], false, NULL)); + if (unload_image_module_sp.get()) { - for (old_idx = idx; old_idx < old_dyld_all_image_infos.size(); ++old_idx) - { - if (m_dyld_image_infos[idx].file_spec == old_dyld_all_image_infos[old_idx].file_spec) - { - old_dyld_all_image_infos[old_idx].address = LLDB_INVALID_ADDRESS; - break; - } - } + UnloadImageLoadAddress (unload_image_module_sp.get(), image_infos[idx]); + unloaded_module_list.AppendIfNeeded (unload_image_module_sp); } - - for (old_idx = 0; old_idx < old_dyld_all_image_infos.size(); ++old_idx) + else { - if (old_dyld_all_image_infos[old_idx].address != LLDB_INVALID_ADDRESS) + if (log) { - if (log) - old_dyld_all_image_infos[old_idx].PutToLog (log.get()); - ModuleSP unload_image_module_sp (FindTargetModuleForDYLDImageInfo (old_dyld_all_image_infos[old_idx], false, NULL)); - if (unload_image_module_sp.get()) - { - if (UnloadImageLoadAddress (unload_image_module_sp.get(), old_dyld_all_image_infos[old_idx])) - unloaded_module_list.AppendIfNeeded (unload_image_module_sp); - } + log->Printf ("Could not find module for unloading info entry:"); + image_infos[idx].PutToLog(log.get()); } } + + // Then remove it from the m_dyld_image_infos: + + m_dyld_image_infos.erase(pos); + break; } - - if (unloaded_module_list.GetSize() > 0) + } + + if (pos == end) + { + if (log) { - if (log) - { - log->PutCString("Unloaded:"); - unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload"); - } - m_process->GetTarget().ModulesDidUnload (unloaded_module_list); + log->Printf ("Could not find image_info entry for unloading image:"); + image_infos[idx].PutToLog(log.get()); } } - else + } + if (unloaded_module_list.GetSize() > 0) + { + if (log) { - if (log) - PutToLog(log.get()); + log->PutCString("Unloaded:"); + unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload"); + } + m_process->GetTarget().ModulesDidUnload (unloaded_module_list); + } + m_dyld_image_infos_stop_id = m_process->GetStopID(); + return true; +} + +bool +DynamicLoaderMacOSXDYLD::ReadImageInfos (lldb::addr_t image_infos_addr, + uint32_t image_infos_count, + DYLDImageInfo::collection &image_infos) +{ + const ByteOrder endian = m_dyld.GetByteOrder(); + const uint32_t addr_size = m_dyld.GetAddressByteSize(); + + image_infos.resize(image_infos_count); + const size_t count = image_infos.size() * 3 * addr_size; + DataBufferHeap info_data(count, 0); + Error error; + const size_t bytes_read = m_process->ReadMemory (image_infos_addr, + info_data.GetBytes(), + info_data.GetByteSize(), + error); + if (bytes_read == count) + { + uint32_t info_data_offset = 0; + DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size); + for (int i = 0; i < image_infos.size() && info_data_ref.ValidOffset(info_data_offset); i++) + { + image_infos[i].address = info_data_ref.GetPointer(&info_data_offset); + lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset); + image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset); + + char raw_path[PATH_MAX]; + m_process->ReadCStringFromMemory (path_addr, raw_path, sizeof(raw_path)); + // don't resolve the path + const bool resolve_path = false; + image_infos[i].file_spec.SetFile(raw_path, resolve_path); } - m_dyld_image_infos_stop_id = m_process->GetStopID(); + return true; } else { - m_dyld_image_infos.clear(); + return false; } +} - const uint32_t num_dylibs = m_dyld_image_infos.size(); - if (num_dylibs > 0) +//---------------------------------------------------------------------- +// If we have found where the "_dyld_all_image_infos" lives in memory, +// read the current info from it, and then update all image load +// addresses (or lack thereof). Only do this if this is the first time +// we're reading the dyld infos. Return true if we actually read anything, +// and false otherwise. +//---------------------------------------------------------------------- +bool +DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos () +{ + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + + Mutex::Locker locker(m_mutex); + if (m_process->GetStopID() == m_dyld_image_infos_stop_id + || m_dyld_image_infos.size() != 0) + return false; + + if (ReadAllImageInfosStructure ()) { - ModuleList loaded_module_list; - for (uint32_t idx = 0; idx<num_dylibs; ++idx) + if (m_dyld_all_image_infos.dylib_info_count > 0) { - ModuleSP image_module_sp (FindTargetModuleForDYLDImageInfo (m_dyld_image_infos[idx], true, NULL)); - - if (image_module_sp) + if (m_dyld_all_image_infos.dylib_info_addr == 0) { - if (m_dyld_image_infos[idx].header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor) - image_module_sp->SetIsDynamicLinkEditor (true); - - ObjectFile *objfile = image_module_sp->GetObjectFile (); - if (objfile) - { - SectionList *sections = objfile->GetSectionList(); - if (sections) - { - ConstString commpage_dbstr("__commpage"); - Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get(); - if (commpage_section) - { - const FileSpec objfile_file_spec = objfile->GetFileSpec(); - ArchSpec arch (m_dyld_image_infos[idx].GetArchitecture ()); - ModuleSP commpage_image_module_sp(target_images.FindFirstModuleForFileSpec (objfile_file_spec, &arch, &commpage_dbstr)); - if (!commpage_image_module_sp) - { - commpage_image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec, - arch, - NULL, - &commpage_dbstr, - objfile->GetOffset() + commpage_section->GetFileOffset()); - } - if (commpage_image_module_sp) - UpdateCommPageLoadAddress (commpage_image_module_sp.get()); - } - } - } - - // UpdateImageLoadAddress will return true if any segments - // change load address. We need to check this so we don't - // mention that all loaded shared libraries are newly loaded - // each time we hit out dyld breakpoint since dyld will list all - // shared libraries each time. - if (UpdateImageLoadAddress (image_module_sp.get(), m_dyld_image_infos[idx])) - { - loaded_module_list.AppendIfNeeded (image_module_sp); - } + // DYLD is updating the images now. So we should say we have no images, and then we'll + // figure it out when we hit the added breakpoint. + return false; } - } - if (loaded_module_list.GetSize() > 0) - { - // FIXME: This should really be in the Runtime handlers class, which should get - // called by the target's ModulesDidLoad, but we're doing it all locally for now - // to save time. - // Also, I'm assuming there can be only one libobjc dylib loaded... - - ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime(); - if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary()) + else { - size_t num_modules = loaded_module_list.GetSize(); - for (int i = 0; i < num_modules; i++) + if (!AddModulesUsingImageInfosAddress (m_dyld_all_image_infos.dylib_info_addr, + m_dyld_all_image_infos.dylib_info_count)) { - if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i))) - { - objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i)); - break; - } + DEBUG_PRINTF( "unable to read all data for all_dylib_infos."); + m_dyld_image_infos.clear(); } } - if (log) - loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidLoad"); - m_process->GetTarget().ModulesDidLoad (loaded_module_list); } + return true; } - return m_dyld_image_infos.size(); + else + return false; } //---------------------------------------------------------------------- @@ -968,40 +1104,41 @@ DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, DYLDImage // Read the mach_header and load commands for each image that the // _dyld_all_image_infos structure points to and cache the results. //---------------------------------------------------------------------- + void -DynamicLoaderMacOSXDYLD::UpdateAllImageInfosHeaderAndLoadCommands() +DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos, + uint32_t infos_count, + bool update_executable) { uint32_t exe_idx = UINT32_MAX; LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); // Read any UUID values that we can get - for (uint32_t i = 0; i < m_dyld_all_image_infos.dylib_info_count; i++) + for (uint32_t i = 0; i < infos_count; i++) { - if (!m_dyld_image_infos[i].UUIDValid()) + if (!image_infos[i].UUIDValid()) { DataExtractor data; // Load command data - if (!ReadMachHeader (m_dyld_image_infos[i].address, &m_dyld_image_infos[i].header, &data)) + if (!ReadMachHeader (image_infos[i].address, &image_infos[i].header, &data)) continue; - ParseLoadCommands (data, m_dyld_image_infos[i], NULL); + ParseLoadCommands (data, image_infos[i], NULL); - if (m_dyld_image_infos[i].header.filetype == llvm::MachO::HeaderFileTypeExecutable) + if (image_infos[i].header.filetype == llvm::MachO::HeaderFileTypeExecutable) exe_idx = i; - if (log) - m_dyld_image_infos[i].PutToLog (log.get()); } } - if (exe_idx < m_dyld_image_infos.size()) + if (exe_idx < image_infos.size()) { - ModuleSP exe_module_sp (FindTargetModuleForDYLDImageInfo (m_dyld_image_infos[exe_idx], false, NULL)); + ModuleSP exe_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[exe_idx], false, NULL)); if (!exe_module_sp) { - ArchSpec exe_arch_spec (m_dyld_image_infos[exe_idx].GetArchitecture ()); - exe_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[exe_idx].file_spec, + ArchSpec exe_arch_spec (image_infos[exe_idx].GetArchitecture ()); + exe_module_sp = m_process->GetTarget().GetSharedModule (image_infos[exe_idx].file_spec, exe_arch_spec, - &m_dyld_image_infos[exe_idx].uuid); + &image_infos[exe_idx].uuid); } if (exe_module_sp) diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h index 4591b6966f8..c6f55ffc674 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h @@ -103,19 +103,11 @@ protected: bool ReadDYLDInfoFromMemoryAndSetNotificationCallback (lldb::addr_t addr); - uint32_t - UpdateAllImageInfos (); - static bool NotifyBreakpointHit (void *baton, lldb_private::StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); - void - UpdateAllImageInfosHeaderAndLoadCommands (); - - bool - UpdateCommPageLoadAddress (lldb_private::Module *module); uint32_t AddrByteSize() @@ -380,8 +372,42 @@ protected: bool SetNotificationBreakpoint (); + // There is a little tricky bit where you might initially attach while dyld is updating + // the all_image_infos, and you can't read the infos, so you have to continue and pick it + // up when you hit the update breakpoint. At that point, you need to run this initialize + // function, but when you do it that way you DON'T need to do the extra work you would at + // the breakpoint. + // So this function will only do actual work if the image infos haven't been read yet. + // If it does do any work, then it will return true, and false otherwise. That way you can + // call it in the breakpoint action, and if it returns true you're done. + bool + InitializeFromAllImageInfos (); + bool ReadAllImageInfosStructure (); + + bool + AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count); + + bool + AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos); + + bool + RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count); + + void + UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos, + uint32_t infos_count, + bool update_executable); + + bool + UpdateCommPageLoadAddress (lldb_private::Module *module); + + bool + ReadImageInfos (lldb::addr_t image_infos_addr, + uint32_t image_infos_count, + DYLDImageInfo::collection &image_infos); + DYLDImageInfo m_dyld; // Info about the current dyld being used lldb::addr_t m_dyld_all_image_infos_addr; diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index e95521d4551..6bb9f700ef0 100644 --- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -27,6 +27,8 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, Thread *thread = process->GetThreadList().GetSelectedThread().get(); if (thread == NULL) thread = process->GetThreadList().GetThreadAtIndex(0).get(); + if (thread == NULL) + return false; const bool append = true; const bool include_symbols = true; diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 19a10576bd1..79310dd11ad 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -1897,6 +1897,9 @@ Process::ReadScalarIntegerFromMemory (addr_t addr, addr_t Process::AllocateMemory(size_t size, uint32_t permissions, Error &error) { + if (GetPrivateState() != eStateStopped) + return LLDB_INVALID_ADDRESS; + #if defined (USE_ALLOCATE_MEMORY_CACHE) return m_allocated_memory_cache.AllocateMemory(size, permissions, error); #else diff --git a/lldb/test/types/AbstractBase.py b/lldb/test/types/AbstractBase.py index 559fa7f803c..c7ae11cc3de 100644 --- a/lldb/test/types/AbstractBase.py +++ b/lldb/test/types/AbstractBase.py @@ -44,8 +44,13 @@ class GenericTester(TestBase): # Bring the program to the point where we can issue a series of # 'frame variable -T' command. self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) - self.runCmd("breakpoint set --name Puts") - self.runCmd("run", RUN_SUCCEEDED) + puts_line = line_number ("basic_type.cpp", "// Here is the line we will break on before stepping out") + self.expect("breakpoint set -f basic_type.cpp -l %d" % puts_line, + BREAKPOINT_CREATED, + startstr = "Breakpoint created: 1: file ='basic_type.cpp', line = %d, locations = 1" % + puts_line) + + self.expect("run", RUN_SUCCEEDED, patterns = [".*"]) self.runCmd("thread step-out", STEP_OUT_SUCCEEDED) #self.runCmd("frame variable -T") @@ -104,8 +109,16 @@ class GenericTester(TestBase): # Bring the program to the point where we can issue a series of # 'expr' command. self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) - self.runCmd("breakpoint set --name Puts") - self.runCmd("run", RUN_SUCCEEDED) + #self.runCmd("breakpoint set --name Puts") + #self.runCmd("run", RUN_SUCCEEDED) + puts_line = line_number ("basic_type.cpp", "// Here is the line we will break on before stepping out") + self.expect("breakpoint set -f basic_type.cpp -l %d" % puts_line, + BREAKPOINT_CREATED, + startstr = "Breakpoint created: 1: file ='basic_type.cpp', line = %d, locations = 1" % + puts_line) + self.expect("run", RUN_SUCCEEDED, patterns = [".*"]) + self.runCmd ("process status") + self.runCmd("thread step-out", STEP_OUT_SUCCEEDED) #self.runCmd("frame variable -T") diff --git a/lldb/test/types/basic_type.cpp b/lldb/test/types/basic_type.cpp index a2e9df305ef..75ad397cf49 100644 --- a/lldb/test/types/basic_type.cpp +++ b/lldb/test/types/basic_type.cpp @@ -84,7 +84,7 @@ typedef struct a_union_nonzero_tag { void Puts(char const *msg) { - puts(msg); + puts(msg); // Here is the line we will break on before stepping out } int |