diff options
Diffstat (limited to 'source/Target')
-rw-r--r-- | source/Target/Platform.cpp | 368 | ||||
-rw-r--r-- | source/Target/Process.cpp | 106 | ||||
-rw-r--r-- | source/Target/RegisterContext.cpp | 12 | ||||
-rw-r--r-- | source/Target/StackFrameList.cpp | 19 | ||||
-rw-r--r-- | source/Target/SystemRuntime.cpp | 10 | ||||
-rw-r--r-- | source/Target/Target.cpp | 106 | ||||
-rw-r--r-- | source/Target/Thread.cpp | 105 | ||||
-rw-r--r-- | source/Target/ThreadPlanCallFunction.cpp | 167 | ||||
-rw-r--r-- | source/Target/ThreadPlanCallUserExpression.cpp | 10 | ||||
-rw-r--r-- | source/Target/ThreadPlanStepInRange.cpp | 4 |
10 files changed, 646 insertions, 261 deletions
diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp index 75d94bd..66f9c0e 100644 --- a/source/Target/Platform.cpp +++ b/source/Target/Platform.cpp @@ -237,6 +237,7 @@ Platform::Platform (bool is_host) : m_system_arch_set_while_connected (false), m_sdk_sysroot (), m_sdk_build (), + m_working_dir (), m_remote_url (), m_name (), m_major_os_version (UINT32_MAX), @@ -319,6 +320,10 @@ Platform::GetStatus (Stream &strm) strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no"); } + if (GetWorkingDirectory()) + { + strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetCString()); + } if (!IsConnected()) return; @@ -405,12 +410,332 @@ Platform::GetOSKernelDescription (std::string &s) } ConstString +Platform::GetWorkingDirectory () +{ + if (IsHost()) + { + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd))) + return ConstString(cwd); + else + return ConstString(); + } + else + { + if (!m_working_dir) + m_working_dir = GetRemoteWorkingDirectory(); + return m_working_dir; + } +} + + +struct RecurseCopyBaton +{ + const FileSpec& dst; + Platform *platform_ptr; + Error error; +}; + + +static FileSpec::EnumerateDirectoryResult +RecurseCopy_Callback (void *baton, + FileSpec::FileType file_type, + const FileSpec &src) +{ + RecurseCopyBaton* rc_baton = (RecurseCopyBaton*)baton; + switch (file_type) + { + case FileSpec::eFileTypePipe: + case FileSpec::eFileTypeSocket: + // we have no way to copy pipes and sockets - ignore them and continue + return FileSpec::eEnumerateDirectoryResultNext; + break; + + case FileSpec::eFileTypeDirectory: + { + // make the new directory and get in there + FileSpec dst_dir = rc_baton->dst; + if (!dst_dir.GetFilename()) + dst_dir.GetFilename() = src.GetLastPathComponent(); + std::string dst_dir_path (dst_dir.GetPath()); + Error error = rc_baton->platform_ptr->MakeDirectory(dst_dir_path.c_str(), lldb::eFilePermissionsDirectoryDefault); + if (error.Fail()) + { + rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end", dst_dir_path.c_str()); + return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out + } + + // now recurse + std::string src_dir_path (src.GetPath()); + + // Make a filespec that only fills in the directory of a FileSpec so + // when we enumerate we can quickly fill in the filename for dst copies + FileSpec recurse_dst; + recurse_dst.GetDirectory().SetCString(dst_dir.GetPath().c_str()); + RecurseCopyBaton rc_baton2 = { recurse_dst, rc_baton->platform_ptr, Error() }; + FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &rc_baton2); + if (rc_baton2.error.Fail()) + { + rc_baton->error.SetErrorString(rc_baton2.error.AsCString()); + return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out + } + return FileSpec::eEnumerateDirectoryResultNext; + } + break; + + case FileSpec::eFileTypeSymbolicLink: + { + // copy the file and keep going + FileSpec dst_file = rc_baton->dst; + if (!dst_file.GetFilename()) + dst_file.GetFilename() = src.GetFilename(); + + char buf[PATH_MAX]; + + rc_baton->error = Host::Readlink (src.GetPath().c_str(), buf, sizeof(buf)); + + if (rc_baton->error.Fail()) + return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out + + rc_baton->error = rc_baton->platform_ptr->CreateSymlink(dst_file.GetPath().c_str(), buf); + + if (rc_baton->error.Fail()) + return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out + + return FileSpec::eEnumerateDirectoryResultNext; + } + break; + case FileSpec::eFileTypeRegular: + { + // copy the file and keep going + FileSpec dst_file = rc_baton->dst; + if (!dst_file.GetFilename()) + dst_file.GetFilename() = src.GetFilename(); + Error err = rc_baton->platform_ptr->PutFile(src, dst_file); + if (err.Fail()) + { + rc_baton->error.SetErrorString(err.AsCString()); + return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out + } + return FileSpec::eEnumerateDirectoryResultNext; + } + break; + + case FileSpec::eFileTypeInvalid: + case FileSpec::eFileTypeOther: + case FileSpec::eFileTypeUnknown: + rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s", src.GetPath().c_str()); + return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out + break; + } +} + +Error +Platform::Install (const FileSpec& src, const FileSpec& dst) +{ + Error error; + + Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); + if (log) + log->Printf ("Platform::Install (src='%s', dst='%s')", src.GetPath().c_str(), dst.GetPath().c_str()); + FileSpec fixed_dst(dst); + + if (!fixed_dst.GetFilename()) + fixed_dst.GetFilename() = src.GetFilename(); + + ConstString working_dir = GetWorkingDirectory(); + + if (dst) + { + if (dst.GetDirectory()) + { + const char first_dst_dir_char = dst.GetDirectory().GetCString()[0]; + if (first_dst_dir_char == '/' || first_dst_dir_char == '\\') + { + fixed_dst.GetDirectory() = dst.GetDirectory(); + } + // If the fixed destination file doesn't have a directory yet, + // then we must have a relative path. We will resolve this relative + // path against the platform's working directory + if (!fixed_dst.GetDirectory()) + { + FileSpec relative_spec; + std::string path; + if (working_dir) + { + relative_spec.SetFile(working_dir.GetCString(), false); + relative_spec.AppendPathComponent(dst.GetPath().c_str()); + fixed_dst.GetDirectory() = relative_spec.GetDirectory(); + } + else + { + error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str()); + return error; + } + } + } + else + { + if (working_dir) + { + fixed_dst.GetDirectory() = working_dir; + } + else + { + error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str()); + return error; + } + } + } + else + { + if (working_dir) + { + fixed_dst.GetDirectory() = working_dir; + } + else + { + error.SetErrorStringWithFormat("platform working directory must be valid when destination directory is empty"); + return error; + } + } + + if (log) + log->Printf ("Platform::Install (src='%s', dst='%s') fixed_dst='%s'", src.GetPath().c_str(), dst.GetPath().c_str(), fixed_dst.GetPath().c_str()); + + if (GetSupportsRSync()) + { + error = PutFile(src, dst); + } + else + { + switch (src.GetFileType()) + { + case FileSpec::eFileTypeDirectory: + { + if (GetFileExists (fixed_dst)) + Unlink (fixed_dst.GetPath().c_str()); + uint32_t permissions = src.GetPermissions(); + if (permissions == 0) + permissions = eFilePermissionsDirectoryDefault; + std::string dst_dir_path(fixed_dst.GetPath()); + error = MakeDirectory(dst_dir_path.c_str(), permissions); + if (error.Success()) + { + // Make a filespec that only fills in the directory of a FileSpec so + // when we enumerate we can quickly fill in the filename for dst copies + FileSpec recurse_dst; + recurse_dst.GetDirectory().SetCString(dst_dir_path.c_str()); + std::string src_dir_path (src.GetPath()); + RecurseCopyBaton baton = { recurse_dst, this, Error() }; + FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &baton); + return baton.error; + } + } + break; + + case FileSpec::eFileTypeRegular: + if (GetFileExists (fixed_dst)) + Unlink (fixed_dst.GetPath().c_str()); + error = PutFile(src, fixed_dst); + break; + + case FileSpec::eFileTypeSymbolicLink: + { + if (GetFileExists (fixed_dst)) + Unlink (fixed_dst.GetPath().c_str()); + char buf[PATH_MAX]; + error = Host::Readlink(src.GetPath().c_str(), buf, sizeof(buf)); + if (error.Success()) + error = CreateSymlink(dst.GetPath().c_str(), buf); + } + break; + case FileSpec::eFileTypePipe: + error.SetErrorString("platform install doesn't handle pipes"); + break; + case FileSpec::eFileTypeSocket: + error.SetErrorString("platform install doesn't handle sockets"); + break; + case FileSpec::eFileTypeInvalid: + case FileSpec::eFileTypeUnknown: + case FileSpec::eFileTypeOther: + error.SetErrorString("platform install doesn't handle non file or directory items"); + break; + } + } + return error; +} + +bool +Platform::SetWorkingDirectory (const ConstString &path) +{ + if (IsHost()) + { + Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); + if (log) + log->Printf("Platform::SetWorkingDirectory('%s')", path.GetCString()); +#ifdef _WIN32 + // Not implemented on Windows + return false; +#else + if (path) + { + if (chdir(path.GetCString()) == 0) + return true; + } + return false; +#endif + } + else + { + m_working_dir.Clear(); + return SetRemoteWorkingDirectory(path); + } +} + +Error +Platform::MakeDirectory (const char *path, uint32_t permissions) +{ + if (IsHost()) + return Host::MakeDirectory (path, permissions); + else + { + Error error; + error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__); + return error; + } +} + +Error +Platform::GetFilePermissions (const char *path, uint32_t &file_permissions) +{ + if (IsHost()) + return Host::GetFilePermissions(path, file_permissions); + else + { + Error error; + error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__); + return error; + } +} + +Error +Platform::SetFilePermissions (const char *path, uint32_t file_permissions) +{ + if (IsHost()) + return Host::SetFilePermissions(path, file_permissions); + else + { + Error error; + error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__); + return error; + } +} + +ConstString Platform::GetName () { - const char *name = GetHostname(); - if (name == NULL || name[0] == '\0') - return GetPluginName(); - return ConstString (name); + return GetPluginName(); } const char * @@ -424,6 +749,16 @@ Platform::GetHostname () return m_name.c_str(); } +bool +Platform::SetRemoteWorkingDirectory(const ConstString &path) +{ + Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); + if (log) + log->Printf("Platform::SetRemoteWorkingDirectory('%s')", path.GetCString()); + m_working_dir = path; + return true; +} + const char * Platform::GetUserName (uint32_t uid) { @@ -779,14 +1114,6 @@ Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, return false; } -uint32_t -Platform::MakeDirectory (const FileSpec &spec, - mode_t mode) -{ - std::string path(spec.GetPath()); - return this->MakeDirectory(path,mode); -} - Error Platform::PutFile (const FileSpec& source, const FileSpec& destination, @@ -805,12 +1132,29 @@ Platform::GetFile (const FileSpec& source, return error; } +Error +Platform::CreateSymlink (const char *src, // The name of the link is in src + const char *dst)// The symlink points to dst +{ + Error error("unimplemented"); + return error; +} + bool Platform::GetFileExists (const lldb_private::FileSpec& file_spec) { return false; } +Error +Platform::Unlink (const char *path) +{ + Error error("unimplemented"); + return error; +} + + + lldb_private::Error Platform::RunShellCommand (const char *command, // Shouldn't be NULL const char *working_dir, // Pass NULL to use the current working directory diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp index 700afdb..1de322a 100644 --- a/source/Target/Process.cpp +++ b/source/Target/Process.cpp @@ -1023,6 +1023,8 @@ Process::Process(Target &target, Listener &listener) : m_thread_mutex (Mutex::eMutexTypeRecursive), m_thread_list_real (this), m_thread_list (this), + m_extended_thread_list (this), + m_extended_thread_stop_id (0), m_notifications (), m_image_tokens (), m_listener (listener), @@ -1148,6 +1150,7 @@ Process::Finalize() m_dyld_ap.reset(); m_thread_list_real.Destroy(); m_thread_list.Destroy(); + m_extended_thread_list.Destroy(); std::vector<Notifications> empty_notifications; m_notifications.swap(empty_notifications); m_image_tokens.clear(); @@ -1591,6 +1594,13 @@ Process::UpdateThreadListIfNeeded () m_thread_list_real.Update(real_thread_list); m_thread_list.Update (new_thread_list); m_thread_list.SetStopID (stop_id); + + if (GetLastNaturalStopID () != m_extended_thread_stop_id) + { + // Clear any extended threads that we may have accumulated previously + m_extended_thread_list.Clear(); + m_extended_thread_stop_id = GetLastNaturalStopID (); + } } } } @@ -2103,12 +2113,37 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw } else { - // Report error for setting breakpoint... - m_target.GetDebugger().GetErrorFile().Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n", - load_addr, - owner->GetBreakpoint().GetID(), - owner->GetID(), - error.AsCString() ? error.AsCString() : "unkown error"); + bool show_error = true; + switch (GetState()) + { + case eStateInvalid: + case eStateUnloaded: + case eStateConnected: + case eStateAttaching: + case eStateLaunching: + case eStateDetached: + case eStateExited: + show_error = false; + break; + + case eStateStopped: + case eStateRunning: + case eStateStepping: + case eStateCrashed: + case eStateSuspended: + show_error = IsAlive(); + break; + } + + if (show_error) + { + // Report error for setting breakpoint... + m_target.GetDebugger().GetErrorFile().Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n", + load_addr, + owner->GetBreakpoint().GetID(), + owner->GetID(), + error.AsCString() ? error.AsCString() : "unkown error"); + } } } } @@ -2350,6 +2385,7 @@ Process::DisableSoftwareBreakpoint (BreakpointSite *bp_site) size_t Process::ReadMemory (addr_t addr, void *buf, size_t size, Error &error) { + error.Clear(); if (!GetDisableMemoryCache()) { #if defined (VERIFY_MEMORY_READS) @@ -2873,7 +2909,7 @@ Process::WaitForProcessStopPrivate (const TimeValue *timeout, EventSP &event_sp) } Error -Process::Launch (const ProcessLaunchInfo &launch_info) +Process::Launch (ProcessLaunchInfo &launch_info) { Error error; m_abi_sp.reset(); @@ -2891,6 +2927,13 @@ Process::Launch (const ProcessLaunchInfo &launch_info) exe_module->GetPlatformFileSpec().GetPath(platform_exec_file_path, sizeof(platform_exec_file_path)); if (exe_module->GetFileSpec().Exists()) { + // Install anything that might need to be installed prior to launching. + // For host systems, this will do nothing, but if we are connected to a + // remote platform it will install any needed binaries + error = GetTarget().Install(&launch_info); + if (error.Fail()) + return error; + if (PrivateStateThreadIsValid ()) PausePrivateStateThread (); @@ -4697,11 +4740,7 @@ Process::SettingsTerminate () ExecutionResults Process::RunThreadPlan (ExecutionContext &exe_ctx, lldb::ThreadPlanSP &thread_plan_sp, - bool stop_others, - bool run_others, - bool unwind_on_error, - bool ignore_breakpoints, - uint32_t timeout_usec, + const EvaluateExpressionOptions &options, Stream &errors) { ExecutionResults return_value = eExecutionSetupError; @@ -4812,6 +4851,17 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, thread->QueueThreadPlan(thread_plan_sp, false); // This used to pass "true" does that make sense? + if (options.GetDebug()) + { + // In this case, we aren't actually going to run, we just want to stop right away. + // Flush this thread so we will refetch the stacks and show the correct backtrace. + // FIXME: To make this prettier we should invent some stop reason for this, but that + // is only cosmetic, and this functionality is only of use to lldb developers who can + // live with not pretty... + thread->Flush(); + return eExecutionStoppedForDebug; + } + Listener listener("lldb.process.listener.run-thread-plan"); lldb::EventSP event_to_broadcast_sp; @@ -4853,11 +4903,12 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, TimeValue one_thread_timeout = TimeValue::Now(); TimeValue final_timeout = one_thread_timeout; - if (run_others) + uint32_t timeout_usec = options.GetTimeoutUsec(); + if (options.GetTryAllThreads()) { // If we are running all threads then we take half the time to run all threads, bounded by // .25 sec. - if (timeout_usec == 0) + if (options.GetTimeoutUsec() == 0) one_thread_timeout.OffsetWithMicroSeconds(default_one_thread_timeout_usec); else { @@ -4969,7 +5020,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, if (before_first_timeout) { - if (run_others) + if (options.GetTryAllThreads()) timeout_ptr = &one_thread_timeout; else { @@ -5085,7 +5136,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, if (log) log->Printf ("Process::RunThreadPlan() stopped for breakpoint: %s.", stop_info_sp->GetDescription()); return_value = eExecutionHitBreakpoint; - if (!ignore_breakpoints) + if (!options.DoesIgnoreBreakpoints()) { event_to_broadcast_sp = event_sp; } @@ -5094,7 +5145,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, { if (log) log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete."); - if (!unwind_on_error) + if (!options.DoesUnwindOnError()) event_to_broadcast_sp = event_sp; return_value = eExecutionInterrupted; } @@ -5145,7 +5196,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, // either exit, or try with all threads running for the same timeout. if (log) { - if (run_others) + if (options.GetTryAllThreads()) { uint64_t remaining_time = final_timeout - TimeValue::Now(); if (before_first_timeout) @@ -5228,7 +5279,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, continue; } - if (!run_others) + if (!options.GetTryAllThreads()) { if (log) log->PutCString ("Process::RunThreadPlan(): try_all_threads was false, we stopped so now we're quitting."); @@ -5301,8 +5352,8 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, // 1) The execution successfully completed // 2) We hit a breakpoint, and ignore_breakpoints was true // 3) We got some other error, and discard_on_error was true - bool should_unwind = (return_value == eExecutionInterrupted && unwind_on_error) - || (return_value == eExecutionHitBreakpoint && ignore_breakpoints); + bool should_unwind = (return_value == eExecutionInterrupted && options.DoesUnwindOnError()) + || (return_value == eExecutionHitBreakpoint && options.DoesIgnoreBreakpoints()); if (return_value == eExecutionCompleted || should_unwind) @@ -5422,7 +5473,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, if (log) log->PutCString("Process::RunThreadPlan(): execution set up error."); - if (unwind_on_error) + if (options.DoesUnwindOnError()) { thread->DiscardThreadPlansUpToPlan (thread_plan_sp); thread_plan_sp->SetPrivate (orig_plan_private); @@ -5446,7 +5497,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, { if (log) log->PutCString("Process::RunThreadPlan(): thread plan stopped in mid course"); - if (unwind_on_error && thread_plan_sp) + if (options.DoesUnwindOnError() && thread_plan_sp) { if (log) log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause unwind_on_error is set."); @@ -5518,6 +5569,9 @@ Process::ExecutionResultAsCString (ExecutionResults result) case eExecutionTimedOut: result_name = "eExecutionTimedOut"; break; + case eExecutionStoppedForDebug: + result_name = "eExecutionStoppedForDebug"; + break; } return result_name; } @@ -5633,7 +5687,7 @@ Process::DidExec () { Target &target = GetTarget(); target.CleanupProcess (); - target.ClearModules(); + target.ClearModules(false); m_dynamic_checkers_ap.reset(); m_abi_sp.reset(); m_system_runtime_ap.reset(); @@ -5649,5 +5703,9 @@ Process::DidExec () // Flush the process (threads and all stack frames) after running CompleteAttach() // in case the dynamic loader loaded things in new locations. Flush(); + + // After we figure out what was loaded/unloaded in CompleteAttach, + // we need to let the target know so it can do any cleanup it needs to. + target.DidExec(); } diff --git a/source/Target/RegisterContext.cpp b/source/Target/RegisterContext.cpp index 3d68ba8..93dce3e 100644 --- a/source/Target/RegisterContext.cpp +++ b/source/Target/RegisterContext.cpp @@ -440,6 +440,18 @@ RegisterContext::WriteRegisterValueToMemory (const RegisterInfo *reg_info, } +bool +RegisterContext::ReadAllRegisterValues (lldb_private::RegisterCheckpoint ®_checkpoint) +{ + return ReadAllRegisterValues(reg_checkpoint.GetData()); +} + +bool +RegisterContext::WriteAllRegisterValues (const lldb_private::RegisterCheckpoint ®_checkpoint) +{ + return WriteAllRegisterValues(reg_checkpoint.GetData()); +} + TargetSP RegisterContext::CalculateTarget () { diff --git a/source/Target/StackFrameList.cpp b/source/Target/StackFrameList.cpp index eaac361..631a77b 100644 --- a/source/Target/StackFrameList.cpp +++ b/source/Target/StackFrameList.cpp @@ -301,7 +301,7 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx) if (reg_ctx_sp) { - const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc); + const bool success = unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc); // There shouldn't be any way not to get the frame info for frame 0. // But if the unwinder can't make one, lets make one by hand with the // SP as the CFA and see if that gets any further. @@ -329,7 +329,7 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx) } else { - const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc); + const bool success = unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc); if (!success) { // We've gotten to the end of the stack. @@ -451,14 +451,17 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx) { if (end_idx < m_concrete_frames_fetched) return; - - uint32_t num_frames = unwinder->GetFramesUpTo(end_idx); - if (num_frames <= end_idx + 1) + + if (unwinder) { - //Done unwinding. - m_concrete_frames_fetched = UINT32_MAX; + uint32_t num_frames = unwinder->GetFramesUpTo(end_idx); + if (num_frames <= end_idx + 1) + { + //Done unwinding. + m_concrete_frames_fetched = UINT32_MAX; + } + m_frames.resize(num_frames); } - m_frames.resize(num_frames); } } diff --git a/source/Target/SystemRuntime.cpp b/source/Target/SystemRuntime.cpp index 7ce150f..5c07ed3 100644 --- a/source/Target/SystemRuntime.cpp +++ b/source/Target/SystemRuntime.cpp @@ -33,7 +33,8 @@ SystemRuntime::FindPlugin (Process *process) // SystemRuntime constructor //---------------------------------------------------------------------- SystemRuntime::SystemRuntime(Process *process) : - m_process (process) + m_process (process), + m_types () { } @@ -59,15 +60,14 @@ SystemRuntime::ModulesDidLoad (ModuleList &module_list) { } -std::vector<ConstString> +const std::vector<ConstString> & SystemRuntime::GetExtendedBacktraceTypes () { - std::vector<ConstString> types; - return types; + return m_types; } ThreadSP -SystemRuntime::GetExtendedBacktrace (ThreadSP thread, ConstString type) +SystemRuntime::GetExtendedBacktraceThread (ThreadSP thread, ConstString type) { return ThreadSP(); } diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp index 18efd8c..fd9626a 100644 --- a/source/Target/Target.cpp +++ b/source/Target/Target.cpp @@ -192,7 +192,7 @@ Target::Destroy() DeleteCurrentProcess (); m_platform_sp.reset(); m_arch.Clear(); - ClearModules(); + ClearModules(true); m_section_load_list.Clear(); const bool notify = false; m_breakpoint_list.RemoveAll(notify); @@ -1014,9 +1014,9 @@ LoadScriptingResourceForModule (const ModuleSP &module_sp, Target *target) } void -Target::ClearModules() +Target::ClearModules(bool delete_locations) { - ModulesDidUnload (m_images, true); + ModulesDidUnload (m_images, delete_locations); GetSectionLoadList().Clear(); m_images.Clear(); m_scratch_ast_context_ap.reset(); @@ -1025,10 +1025,18 @@ Target::ClearModules() } void +Target::DidExec () +{ + // When a process exec's we need to know about it so we can do some cleanup. + m_breakpoint_list.RemoveInvalidLocations(m_arch); + m_internal_breakpoint_list.RemoveInvalidLocations(m_arch); +} + +void Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TARGET)); - ClearModules(); + ClearModules(false); if (executable_sp.get()) { @@ -1098,7 +1106,7 @@ Target::SetArchitecture (const ArchSpec &arch_spec) m_arch = arch_spec; ModuleSP executable_sp = GetExecutableModule (); - ClearModules(); + ClearModules(true); // Need to do something about unsetting breakpoints. if (executable_sp) @@ -2182,12 +2190,78 @@ Target::RunStopHooks () result.GetImmediateErrorStream()->Flush(); } +const TargetPropertiesSP & +Target::GetGlobalProperties() +{ + static TargetPropertiesSP g_settings_sp; + if (!g_settings_sp) + { + g_settings_sp.reset (new TargetProperties (NULL)); + } + return g_settings_sp; +} + +Error +Target::Install (ProcessLaunchInfo *launch_info) +{ + Error error; + PlatformSP platform_sp (GetPlatform()); + if (platform_sp) + { + if (platform_sp->IsRemote()) + { + if (platform_sp->IsConnected()) + { + // Install all files that have an install path, and always install the + // main executable when connected to a remote platform + const ModuleList& modules = GetImages(); + const size_t num_images = modules.GetSize(); + for (size_t idx = 0; idx < num_images; ++idx) + { + const bool is_main_executable = idx == 0; + ModuleSP module_sp(modules.GetModuleAtIndex(idx)); + if (module_sp) + { + FileSpec local_file (module_sp->GetFileSpec()); + if (local_file) + { + FileSpec remote_file (module_sp->GetRemoteInstallFileSpec()); + if (!remote_file) + { + if (is_main_executable) // TODO: add setting for always installing main executable??? + { + // Always install the main executable + remote_file.GetDirectory() = platform_sp->GetWorkingDirectory(); + remote_file.GetFilename() = module_sp->GetFileSpec().GetFilename(); + } + } + if (remote_file) + { + error = platform_sp->Install(local_file, remote_file); + if (error.Success()) + { + module_sp->SetPlatformFileSpec(remote_file); + if (is_main_executable) + { + if (launch_info) + launch_info->SetExecutableFile(remote_file, false); + } + } + else + break; + } + } + } + } + } + } + } + return error; +} //-------------------------------------------------------------- -// class Target::StopHook +// Target::StopHook //-------------------------------------------------------------- - - Target::StopHook::StopHook (lldb::TargetSP target_sp, lldb::user_id_t uid) : UserID (uid), m_target_sp (target_sp), @@ -2519,6 +2593,9 @@ protected: mutable bool m_got_host_env; }; +//---------------------------------------------------------------------- +// TargetProperties +//---------------------------------------------------------------------- TargetProperties::TargetProperties (Target *target) : Properties () { @@ -2807,17 +2884,10 @@ TargetProperties::GetMemoryModuleLoadLevel() const } -const TargetPropertiesSP & -Target::GetGlobalProperties() -{ - static TargetPropertiesSP g_settings_sp; - if (!g_settings_sp) - { - g_settings_sp.reset (new TargetProperties (NULL)); - } - return g_settings_sp; -} +//---------------------------------------------------------------------- +// Target::TargetEventData +//---------------------------------------------------------------------- const ConstString & Target::TargetEventData::GetFlavorString () { diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp index 98c2601..07f5321 100644 --- a/source/Target/Thread.cpp +++ b/source/Target/Thread.cpp @@ -496,7 +496,19 @@ Thread::ThreadStoppedForAReason (void) bool Thread::CheckpointThreadState (ThreadStateCheckpoint &saved_state) { - if (!SaveFrameZeroState(saved_state.register_backup)) + saved_state.register_backup_sp.reset(); + lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0)); + if (frame_sp) + { + lldb::RegisterCheckpointSP reg_checkpoint_sp(new RegisterCheckpoint(RegisterCheckpoint::Reason::eExpression)); + if (reg_checkpoint_sp) + { + lldb::RegisterContextSP reg_ctx_sp (frame_sp->GetRegisterContext()); + if (reg_ctx_sp && reg_ctx_sp->ReadAllRegisterValues (*reg_checkpoint_sp)) + saved_state.register_backup_sp = reg_checkpoint_sp; + } + } + if (!saved_state.register_backup_sp) return false; saved_state.stop_info_sp = GetStopInfo(); @@ -511,8 +523,26 @@ Thread::CheckpointThreadState (ThreadStateCheckpoint &saved_state) bool Thread::RestoreRegisterStateFromCheckpoint (ThreadStateCheckpoint &saved_state) { - RestoreSaveFrameZero(saved_state.register_backup); - return true; + if (saved_state.register_backup_sp) + { + lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0)); + if (frame_sp) + { + lldb::RegisterContextSP reg_ctx_sp (frame_sp->GetRegisterContext()); + if (reg_ctx_sp) + { + bool ret = reg_ctx_sp->WriteAllRegisterValues (*saved_state.register_backup_sp); + + // Clear out all stack frames as our world just changed. + ClearStackFrames(); + reg_ctx_sp->InvalidateIfNeeded(true); + if (m_unwinder_ap.get()) + m_unwinder_ap->Clear(); + return ret; + } + } + } + return false; } bool @@ -1420,14 +1450,6 @@ Thread::QueueThreadPlanForStepInRange ThreadPlanSP -Thread::QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans) -{ - ThreadPlanSP thread_plan_sp (new ThreadPlanStepOverBreakpoint (*this)); - QueueThreadPlan (thread_plan_sp, abort_other_plans); - return thread_plan_sp; -} - -ThreadPlanSP Thread::QueueThreadPlanForStepOut ( bool abort_other_plans, @@ -1470,25 +1492,6 @@ Thread::QueueThreadPlanForStepThrough (StackID &return_stack_id, bool abort_othe } ThreadPlanSP -Thread::QueueThreadPlanForCallFunction (bool abort_other_plans, - Address& function, - lldb::addr_t arg, - bool stop_other_threads, - bool unwind_on_error, - bool ignore_breakpoints) -{ - ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (*this, - function, - ClangASTType(), - arg, - stop_other_threads, - unwind_on_error, - ignore_breakpoints)); - QueueThreadPlan (thread_plan_sp, abort_other_plans); - return thread_plan_sp; -} - -ThreadPlanSP Thread::QueueThreadPlanForRunToAddress (bool abort_other_plans, Address &target_addr, bool stop_other_threads) @@ -1994,48 +1997,6 @@ Thread::GetStackFrameStatus (Stream& strm, num_frames_with_source); } -bool -Thread::SaveFrameZeroState (RegisterCheckpoint &checkpoint) -{ - lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0)); - if (frame_sp) - { - checkpoint.SetStackID(frame_sp->GetStackID()); - lldb::RegisterContextSP reg_ctx_sp (frame_sp->GetRegisterContext()); - if (reg_ctx_sp) - return reg_ctx_sp->ReadAllRegisterValues (checkpoint.GetData()); - } - return false; -} - -bool -Thread::RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint) -{ - return ResetFrameZeroRegisters (checkpoint.GetData()); -} - -bool -Thread::ResetFrameZeroRegisters (lldb::DataBufferSP register_data_sp) -{ - lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0)); - if (frame_sp) - { - lldb::RegisterContextSP reg_ctx_sp (frame_sp->GetRegisterContext()); - if (reg_ctx_sp) - { - bool ret = reg_ctx_sp->WriteAllRegisterValues (register_data_sp); - - // Clear out all stack frames as our world just changed. - ClearStackFrames(); - reg_ctx_sp->InvalidateIfNeeded(true); - if (m_unwinder_ap.get()) - m_unwinder_ap->Clear(); - return ret; - } - } - return false; -} - Unwind * Thread::GetUnwinder () { diff --git a/source/Target/ThreadPlanCallFunction.cpp b/source/Target/ThreadPlanCallFunction.cpp index c9baaaf..854750b 100644 --- a/source/Target/ThreadPlanCallFunction.cpp +++ b/source/Target/ThreadPlanCallFunction.cpp @@ -55,8 +55,6 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread, if (!abi) return false; - TargetSP target_sp (thread.CalculateTarget()); - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP)); SetBreakpoints(); @@ -74,7 +72,7 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread, return false; } - Module *exe_module = target_sp->GetExecutableModulePointer(); + Module *exe_module = GetTarget().GetExecutableModulePointer(); if (exe_module == NULL) { @@ -107,7 +105,7 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread, } } - start_load_addr = m_start_addr.GetLoadAddress (target_sp.get()); + start_load_addr = m_start_addr.GetLoadAddress (&GetTarget()); // Checkpoint the thread state so we can restore it later. if (log && log->GetVerbose()) @@ -120,7 +118,7 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread, log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData()); return false; } - function_load_addr = m_function_addr.GetLoadAddress (target_sp.get()); + function_load_addr = m_function_addr.GetLoadAddress (&GetTarget()); return true; } @@ -128,109 +126,36 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread, ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, const Address &function, const ClangASTType &return_type, - addr_t arg, - bool stop_other_threads, - bool unwind_on_error, - bool ignore_breakpoints, - addr_t *this_arg, - addr_t *cmd_arg) : + llvm::ArrayRef<addr_t> args, + const EvaluateExpressionOptions &options) : ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), m_valid (false), - m_stop_other_threads (stop_other_threads), + m_stop_other_threads (options.GetStopOthers()), + m_unwind_on_error (options.DoesUnwindOnError()), + m_ignore_breakpoints (options.DoesIgnoreBreakpoints()), + m_debug_execution (options.GetDebug()), + m_trap_exceptions (options.GetTrapExceptions()), m_function_addr (function), m_function_sp (0), m_return_type (return_type), m_takedown_done (false), - m_stop_address (LLDB_INVALID_ADDRESS), - m_unwind_on_error (unwind_on_error), - m_ignore_breakpoints (ignore_breakpoints) + m_should_clear_objc_exception_bp(false), + m_should_clear_cxx_exception_bp (false), + m_stop_address (LLDB_INVALID_ADDRESS) { lldb::addr_t start_load_addr; ABI *abi; lldb::addr_t function_load_addr; if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr)) return; - - if (this_arg && cmd_arg) - { - if (!abi->PrepareTrivialCall (thread, - m_function_sp, - function_load_addr, - start_load_addr, - this_arg, - cmd_arg, - &arg)) - return; - } - else if (this_arg) - { - if (!abi->PrepareTrivialCall (thread, - m_function_sp, - function_load_addr, - start_load_addr, - this_arg, - &arg)) - return; - } - else - { - if (!abi->PrepareTrivialCall (thread, - m_function_sp, - function_load_addr, - start_load_addr, - &arg)) - return; - } - - ReportRegisterState ("Function call was set up. Register state was:"); - m_valid = true; -} - - -ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, - const Address &function, - const ClangASTType &return_type, - bool stop_other_threads, - bool unwind_on_error, - bool ignore_breakpoints, - addr_t *arg1_ptr, - addr_t *arg2_ptr, - addr_t *arg3_ptr, - addr_t *arg4_ptr, - addr_t *arg5_ptr, - addr_t *arg6_ptr) : - ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), - m_valid (false), - m_stop_other_threads (stop_other_threads), - m_function_addr (function), - m_function_sp (0), - m_return_type (return_type), - m_takedown_done (false), - m_stop_address (LLDB_INVALID_ADDRESS), - m_unwind_on_error (unwind_on_error), - m_ignore_breakpoints (ignore_breakpoints) -{ - lldb::addr_t start_load_addr; - ABI *abi; - lldb::addr_t function_load_addr; - if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr)) + if (!abi->PrepareTrivialCall(thread, + m_function_sp, + function_load_addr, + start_load_addr, + args)) return; - if (!abi->PrepareTrivialCall (thread, - m_function_sp, - function_load_addr, - start_load_addr, - arg1_ptr, - arg2_ptr, - arg3_ptr, - arg4_ptr, - arg5_ptr, - arg6_ptr)) - { - return; - } - ReportRegisterState ("Function call was set up. Register state was:"); m_valid = true; @@ -299,7 +224,11 @@ ThreadPlanCallFunction::DoTakedown (bool success) m_takedown_done = true; m_stop_address = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC(); m_real_stop_info_sp = GetPrivateStopInfo (); - m_thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state); + if (!m_thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state)) + { + if (log) + log->Printf("ThreadPlanCallFunction(%p): DoTakedown failed to restore register state", this); + } SetPlanComplete(success); ClearBreakpoints(); if (log && log->GetVerbose()) @@ -560,25 +489,34 @@ void ThreadPlanCallFunction::SetBreakpoints () { ProcessSP process_sp (m_thread.CalculateProcess()); - if (process_sp) + if (m_trap_exceptions && process_sp) { m_cxx_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeC_plus_plus); m_objc_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeObjC); if (m_cxx_language_runtime) + { + m_should_clear_cxx_exception_bp = !m_cxx_language_runtime->ExceptionBreakpointsAreSet(); m_cxx_language_runtime->SetExceptionBreakpoints(); + } if (m_objc_language_runtime) + { + m_should_clear_objc_exception_bp = !m_objc_language_runtime->ExceptionBreakpointsAreSet(); m_objc_language_runtime->SetExceptionBreakpoints(); + } } } void ThreadPlanCallFunction::ClearBreakpoints () { - if (m_cxx_language_runtime) - m_cxx_language_runtime->ClearExceptionBreakpoints(); - if (m_objc_language_runtime) - m_objc_language_runtime->ClearExceptionBreakpoints(); + if (m_trap_exceptions) + { + if (m_cxx_language_runtime && m_should_clear_cxx_exception_bp) + m_cxx_language_runtime->ClearExceptionBreakpoints(); + if (m_objc_language_runtime && m_should_clear_objc_exception_bp) + m_objc_language_runtime->ClearExceptionBreakpoints(); + } } bool @@ -586,21 +524,24 @@ ThreadPlanCallFunction::BreakpointsExplainStop() { StopInfoSP stop_info_sp = GetPrivateStopInfo (); - if ((m_cxx_language_runtime && - m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)) - ||(m_objc_language_runtime && - m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))) + if (m_trap_exceptions) { - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP)); - if (log) - log->Printf ("ThreadPlanCallFunction::BreakpointsExplainStop - Hit an exception breakpoint, setting plan complete."); - - SetPlanComplete(false); - - // If the user has set the ObjC language breakpoint, it would normally get priority over our internal - // catcher breakpoint, but in this case we can't let that happen, so force the ShouldStop here. - stop_info_sp->OverrideShouldStop (true); - return true; + if ((m_cxx_language_runtime && + m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)) + ||(m_objc_language_runtime && + m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))) + { + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP)); + if (log) + log->Printf ("ThreadPlanCallFunction::BreakpointsExplainStop - Hit an exception breakpoint, setting plan complete."); + + SetPlanComplete(false); + + // If the user has set the ObjC language breakpoint, it would normally get priority over our internal + // catcher breakpoint, but in this case we can't let that happen, so force the ShouldStop here. + stop_info_sp->OverrideShouldStop (true); + return true; + } } return false; diff --git a/source/Target/ThreadPlanCallUserExpression.cpp b/source/Target/ThreadPlanCallUserExpression.cpp index 70de1cb..827de3e 100644 --- a/source/Target/ThreadPlanCallUserExpression.cpp +++ b/source/Target/ThreadPlanCallUserExpression.cpp @@ -38,14 +38,10 @@ using namespace lldb_private; ThreadPlanCallUserExpression::ThreadPlanCallUserExpression (Thread &thread, Address &function, - lldb::addr_t arg, - bool stop_other_threads, - bool unwind_on_error, - bool ignore_breakpoints, - lldb::addr_t *this_arg, - lldb::addr_t *cmd_arg, + llvm::ArrayRef<lldb::addr_t> args, + const EvaluateExpressionOptions &options, ClangUserExpression::ClangUserExpressionSP &user_expression_sp) : - ThreadPlanCallFunction (thread, function, ClangASTType(), arg, stop_other_threads, unwind_on_error, ignore_breakpoints, this_arg, cmd_arg), + ThreadPlanCallFunction (thread, function, ClangASTType(), args, options), m_user_expression_sp (user_expression_sp) { // User expressions are generally "User generated" so we should set them up to stop when done. diff --git a/source/Target/ThreadPlanStepInRange.cpp b/source/Target/ThreadPlanStepInRange.cpp index c1f14bd..2cfd29f 100644 --- a/source/Target/ThreadPlanStepInRange.cpp +++ b/source/Target/ThreadPlanStepInRange.cpp @@ -132,9 +132,9 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr) bool stop_others; if (m_stop_others == lldb::eOnlyThisThread) - stop_others = false; - else stop_others = true; + else + stop_others = false; FrameComparison frame_order = CompareCurrentFrameToStartFrame(); |