diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Target')
19 files changed, 828 insertions, 188 deletions
diff --git a/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp b/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp index 8b5731e..7a8b601 100644 --- a/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp +++ b/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp @@ -241,7 +241,15 @@ ExecutionContext::GetAddressByteSize() const return sizeof(void *); } - +lldb::ByteOrder +ExecutionContext::GetByteOrder() const +{ + if (m_target_sp && m_target_sp->GetArchitecture().IsValid()) + m_target_sp->GetArchitecture().GetByteOrder(); + if (m_process_sp) + m_process_sp->GetByteOrder(); + return lldb::endian::InlHostByteOrder(); +} RegisterContext * ExecutionContext::GetRegisterContext () const diff --git a/contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp b/contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp index d2f586a..2fdc253 100644 --- a/contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp +++ b/contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp @@ -268,8 +268,8 @@ LanguageRuntime::CreateExceptionBreakpoint (Target &target, { BreakpointResolverSP resolver_sp(new ExceptionBreakpointResolver(language, catch_bp, throw_bp)); SearchFilterSP filter_sp(new ExceptionSearchFilter(target.shared_from_this(), language)); - - BreakpointSP exc_breakpt_sp (target.CreateBreakpoint (filter_sp, resolver_sp, is_internal)); + bool hardware = false; + BreakpointSP exc_breakpt_sp (target.CreateBreakpoint (filter_sp, resolver_sp, is_internal, hardware)); if (is_internal) exc_breakpt_sp->SetBreakpointKind("exception"); diff --git a/contrib/llvm/tools/lldb/source/Target/Platform.cpp b/contrib/llvm/tools/lldb/source/Target/Platform.cpp index e6d3bc7..75d94bd 100644 --- a/contrib/llvm/tools/lldb/source/Target/Platform.cpp +++ b/contrib/llvm/tools/lldb/source/Target/Platform.cpp @@ -22,6 +22,7 @@ #include "lldb/Host/Host.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/Utils.h" using namespace lldb; using namespace lldb_private; @@ -247,7 +248,13 @@ Platform::Platform (bool is_host) : m_uid_map(), m_gid_map(), m_max_uid_name_len (0), - m_max_gid_name_len (0) + m_max_gid_name_len (0), + m_supports_rsync (false), + m_rsync_opts (), + m_rsync_prefix (), + m_supports_ssh (false), + m_ssh_opts (), + m_ignores_remote_hostname (false) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); if (log) @@ -311,6 +318,14 @@ Platform::GetStatus (Stream &strm) strm.Printf(" Hostname: %s\n", GetHostname()); strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no"); } + + if (!IsConnected()) + return; + + std::string specific_info(GetPlatformSpecificConnectionInformation()); + + if (specific_info.empty() == false) + strm.Printf("Platform-specific connection: %s\n", specific_info.c_str()); } @@ -649,10 +664,12 @@ Platform::LaunchProcess (ProcessLaunchInfo &launch_info) const bool is_localhost = true; const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug); const bool first_arg_is_full_shell_command = false; + uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info); if (!launch_info.ConvertArgumentsForLaunchingInShell (error, is_localhost, will_debug, - first_arg_is_full_shell_command)) + first_arg_is_full_shell_command, + num_resumes)) return error; } @@ -760,9 +777,161 @@ Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, if (compatible_arch_ptr) compatible_arch_ptr->Clear(); 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, + uint32_t uid, + uint32_t gid) +{ + Error error("unimplemented"); + return error; +} + +Error +Platform::GetFile (const FileSpec& source, + const FileSpec& destination) +{ + Error error("unimplemented"); + return error; +} + +bool +Platform::GetFileExists (const lldb_private::FileSpec& file_spec) +{ + return false; +} + +lldb_private::Error +Platform::RunShellCommand (const char *command, // Shouldn't be NULL + const char *working_dir, // Pass NULL to use the current working directory + int *status_ptr, // Pass NULL if you don't want the process exit status + int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit + std::string *command_output, // Pass NULL if you don't want the command output + uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish +{ + if (IsHost()) + return Host::RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); + else + return Error("unimplemented"); +} + + +bool +Platform::CalculateMD5 (const FileSpec& file_spec, + uint64_t &low, + uint64_t &high) +{ + if (IsHost()) + return Host::CalculateMD5(file_spec, low, high); + else + return false; +} + +void +Platform::SetLocalCacheDirectory (const char* local) +{ + m_local_cache_directory.assign(local); +} + +const char* +Platform::GetLocalCacheDirectory () +{ + return m_local_cache_directory.c_str(); +} + +static OptionDefinition +g_rsync_option_table[] = +{ + { LLDB_OPT_SET_ALL, false, "rsync" , 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Enable rsync." }, + { LLDB_OPT_SET_ALL, false, "rsync-opts" , 'R', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName , "Platform-specific options required for rsync to work." }, + { LLDB_OPT_SET_ALL, false, "rsync-prefix" , 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName , "Platform-specific rsync prefix put before the remote path." }, + { LLDB_OPT_SET_ALL, false, "ignore-remote-hostname" , 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Do not automatically fill in the remote hostname when composing the rsync command." }, +}; + +static OptionDefinition +g_ssh_option_table[] = +{ + { LLDB_OPT_SET_ALL, false, "ssh" , 's', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Enable SSH." }, + { LLDB_OPT_SET_ALL, false, "ssh-opts" , 'S', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName , "Platform-specific options required for SSH to work." }, +}; + +static OptionDefinition +g_caching_option_table[] = +{ + { LLDB_OPT_SET_ALL, false, "local-cache-dir" , 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypePath , "Path in which to store local copies of files." }, +}; + +OptionGroupPlatformRSync::OptionGroupPlatformRSync () +{ +} + +OptionGroupPlatformRSync::~OptionGroupPlatformRSync () +{ +} + +const lldb_private::OptionDefinition* +OptionGroupPlatformRSync::GetDefinitions () +{ + return g_rsync_option_table; +} + +void +OptionGroupPlatformRSync::OptionParsingStarting (CommandInterpreter &interpreter) +{ + m_rsync = false; + m_rsync_opts.clear(); + m_rsync_prefix.clear(); + m_ignores_remote_hostname = false; +} + +lldb_private::Error +OptionGroupPlatformRSync::SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_arg) +{ + Error error; + char short_option = (char) GetDefinitions()[option_idx].short_option; + switch (short_option) + { + case 'r': + m_rsync = true; + break; + + case 'R': + m_rsync_opts.assign(option_arg); + break; + + case 'P': + m_rsync_prefix.assign(option_arg); + break; + + case 'i': + m_ignores_remote_hostname = true; + break; + + default: + error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); + break; + } + return error; } +uint32_t +OptionGroupPlatformRSync::GetNumDefinitions () +{ + return llvm::array_lengthof(g_rsync_option_table); +} lldb::BreakpointSP Platform::SetThreadCreationBreakpoint (lldb_private::Target &target) @@ -770,10 +939,108 @@ Platform::SetThreadCreationBreakpoint (lldb_private::Target &target) return lldb::BreakpointSP(); } +OptionGroupPlatformSSH::OptionGroupPlatformSSH () +{ +} + +OptionGroupPlatformSSH::~OptionGroupPlatformSSH () +{ +} + +const lldb_private::OptionDefinition* +OptionGroupPlatformSSH::GetDefinitions () +{ + return g_ssh_option_table; +} + +void +OptionGroupPlatformSSH::OptionParsingStarting (CommandInterpreter &interpreter) +{ + m_ssh = false; + m_ssh_opts.clear(); +} + +lldb_private::Error +OptionGroupPlatformSSH::SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_arg) +{ + Error error; + char short_option = (char) GetDefinitions()[option_idx].short_option; + switch (short_option) + { + case 's': + m_ssh = true; + break; + + case 'S': + m_ssh_opts.assign(option_arg); + break; + + default: + error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); + break; + } + + return error; +} + +uint32_t +OptionGroupPlatformSSH::GetNumDefinitions () +{ + return llvm::array_lengthof(g_ssh_option_table); +} + +OptionGroupPlatformCaching::OptionGroupPlatformCaching () +{ +} + +OptionGroupPlatformCaching::~OptionGroupPlatformCaching () +{ +} + +const lldb_private::OptionDefinition* +OptionGroupPlatformCaching::GetDefinitions () +{ + return g_caching_option_table; +} + +void +OptionGroupPlatformCaching::OptionParsingStarting (CommandInterpreter &interpreter) +{ + m_cache_dir.clear(); +} + +lldb_private::Error +OptionGroupPlatformCaching::SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_arg) +{ + Error error; + char short_option = (char) GetDefinitions()[option_idx].short_option; + switch (short_option) + { + case 'c': + m_cache_dir.assign(option_arg); + break; + + default: + error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); + break; + } + + return error; +} + +uint32_t +OptionGroupPlatformCaching::GetNumDefinitions () +{ + return llvm::array_lengthof(g_caching_option_table); +} + size_t Platform::GetEnvironment (StringList &environment) { environment.Clear(); return false; } - diff --git a/contrib/llvm/tools/lldb/source/Target/Process.cpp b/contrib/llvm/tools/lldb/source/Target/Process.cpp index 6edb939..700afdb 100644 --- a/contrib/llvm/tools/lldb/source/Target/Process.cpp +++ b/contrib/llvm/tools/lldb/source/Target/Process.cpp @@ -35,12 +35,17 @@ #include "lldb/Target/Platform.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" +#include "lldb/Target/SystemRuntime.h" #include "lldb/Target/Target.h" #include "lldb/Target/TargetList.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanBase.h" +#ifndef LLDB_DISABLE_POSIX +#include <spawn.h> +#endif + using namespace lldb; using namespace lldb_private; @@ -485,7 +490,8 @@ bool ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell (Error &error, bool localhost, bool will_debug, - bool first_arg_is_full_shell_command) + bool first_arg_is_full_shell_command, + int32_t num_resumes) { error.Clear(); @@ -567,14 +573,14 @@ ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell (Error &error, // 1 - stop in shell // 2 - stop in /usr/bin/arch // 3 - then we will stop in our program - SetResumeCount(2); + SetResumeCount(num_resumes + 1); } else { // Set the resume count to 1: // 1 - stop in shell // 2 - then we will stop in our program - SetResumeCount(1); + SetResumeCount(num_resumes); } } @@ -663,8 +669,9 @@ ProcessLaunchInfo::FileAction::Duplicate (int fd, int dup_fd) +#ifndef LLDB_DISABLE_POSIX bool -ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (posix_spawn_file_actions_t *file_actions, +ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (void *_file_actions, const FileAction *info, Log *log, Error& error) @@ -672,6 +679,8 @@ ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (posix_spawn_file_actions if (info == NULL) return false; + posix_spawn_file_actions_t *file_actions = reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions); + switch (info->m_action) { case eFileActionNone: @@ -733,6 +742,7 @@ ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (posix_spawn_file_actions } return error.Success(); } +#endif Error ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) @@ -808,7 +818,7 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op if (option_arg && option_arg[0]) launch_info.SetShell (option_arg); else - launch_info.SetShell ("/bin/bash"); + launch_info.SetShell (LLDB_DEFAULT_SHELL); break; case 'v': @@ -826,21 +836,21 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op OptionDefinition ProcessLaunchCommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."}, -{ LLDB_OPT_SET_ALL, false, "disable-aslr", 'A', no_argument, NULL, 0, eArgTypeNone, "Disable address space layout randomization when launching a process."}, -{ LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, -{ LLDB_OPT_SET_ALL, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."}, -{ LLDB_OPT_SET_ALL, false, "arch", 'a', required_argument, NULL, 0, eArgTypeArchitecture, "Set the architecture for the process to launch when ambiguous."}, -{ LLDB_OPT_SET_ALL, false, "environment", 'v', required_argument, NULL, 0, eArgTypeNone, "Specify an environment variable name/value stirng (--environement NAME=VALUE). Can be specified multiple times for subsequent environment entries."}, -{ LLDB_OPT_SET_ALL, false, "shell", 'c', optional_argument, NULL, 0, eArgTypeFilename, "Run the process in a shell (not supported on all platforms)."}, +{ LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."}, +{ LLDB_OPT_SET_ALL, false, "disable-aslr", 'A', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Disable address space layout randomization when launching a process."}, +{ LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, +{ LLDB_OPT_SET_ALL, false, "working-dir", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."}, +{ LLDB_OPT_SET_ALL, false, "arch", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeArchitecture, "Set the architecture for the process to launch when ambiguous."}, +{ LLDB_OPT_SET_ALL, false, "environment", 'v', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone, "Specify an environment variable name/value string (--environment NAME=VALUE). Can be specified multiple times for subsequent environment entries."}, +{ LLDB_OPT_SET_ALL, false, "shell", 'c', OptionParser::eOptionalArgument, NULL, 0, eArgTypeFilename, "Run the process in a shell (not supported on all platforms)."}, -{ LLDB_OPT_SET_1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypeFilename, "Redirect stdin for the process to <filename>."}, -{ LLDB_OPT_SET_1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypeFilename, "Redirect stdout for the process to <filename>."}, -{ LLDB_OPT_SET_1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypeFilename, "Redirect stderr for the process to <filename>."}, +{ LLDB_OPT_SET_1 , false, "stdin", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Redirect stdin for the process to <filename>."}, +{ LLDB_OPT_SET_1 , false, "stdout", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Redirect stdout for the process to <filename>."}, +{ LLDB_OPT_SET_1 , false, "stderr", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Redirect stderr for the process to <filename>."}, -{ LLDB_OPT_SET_2 , false, "tty", 't', no_argument, NULL, 0, eArgTypeNone, "Start the process in a terminal (not supported on all platforms)."}, +{ LLDB_OPT_SET_2 , false, "tty", 't', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Start the process in a terminal (not supported on all platforms)."}, -{ LLDB_OPT_SET_3 , false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."}, +{ LLDB_OPT_SET_3 , false, "no-stdio", 'n', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."}, { 0 , false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -1134,6 +1144,7 @@ Process::Finalize() m_dynamic_checkers_ap.reset(); m_abi_sp.reset(); m_os_ap.reset(); + m_system_runtime_ap.reset(); m_dyld_ap.reset(); m_thread_list_real.Destroy(); m_thread_list.Destroy(); @@ -1221,7 +1232,7 @@ Process::GetNextEvent (EventSP &event_sp) StateType -Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr) +Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr, bool wait_always) { // We can't just wait for a "stopped" event, because the stopped event may have restarted the target. // We have to actually check each event, and in the case of a stopped event check the restarted flag @@ -1234,6 +1245,19 @@ Process::WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp if (state == eStateDetached || state == eStateExited) return state; + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf ("Process::%s (timeout = %p)", __FUNCTION__, timeout); + + if (!wait_always && + StateIsStoppedState(state, true) && + StateIsStoppedState(GetPrivateState(), true)) { + if (log) + log->Printf("Process::%s returning without waiting for events; process private and public states are already 'stopped'.", + __FUNCTION__); + return state; + } + while (state != eStateInvalid) { EventSP event_sp; @@ -1792,35 +1816,36 @@ Process::LoadImage (const FileSpec &image_spec, Error &error) { ExecutionContext exe_ctx; frame_sp->CalculateExecutionContext (exe_ctx); - const bool unwind_on_error = true; - const bool ignore_breakpoints = true; + EvaluateExpressionOptions expr_options; + expr_options.SetUnwindOnError(true); + expr_options.SetIgnoreBreakpoints(true); + expr_options.SetExecutionPolicy(eExecutionPolicyAlways); StreamString expr; expr.Printf("dlopen (\"%s\", 2)", path); const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n"; lldb::ValueObjectSP result_valobj_sp; + Error expr_error; ClangUserExpression::Evaluate (exe_ctx, - eExecutionPolicyAlways, - lldb::eLanguageTypeUnknown, - ClangUserExpression::eResultTypeAny, - unwind_on_error, - ignore_breakpoints, + expr_options, expr.GetData(), prefix, result_valobj_sp, - true, - ClangUserExpression::kDefaultTimeout); - error = result_valobj_sp->GetError(); - if (error.Success()) + expr_error); + if (expr_error.Success()) { - Scalar scalar; - if (result_valobj_sp->ResolveValue (scalar)) + error = result_valobj_sp->GetError(); + if (error.Success()) { - addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS); - if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS) + Scalar scalar; + if (result_valobj_sp->ResolveValue (scalar)) { - uint32_t image_token = m_image_tokens.size(); - m_image_tokens.push_back (image_ptr); - return image_token; + addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS); + if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS) + { + uint32_t image_token = m_image_tokens.size(); + m_image_tokens.push_back (image_ptr); + return image_token; + } } } } @@ -1869,23 +1894,21 @@ Process::UnloadImage (uint32_t image_token) { ExecutionContext exe_ctx; frame_sp->CalculateExecutionContext (exe_ctx); - const bool unwind_on_error = true; - const bool ignore_breakpoints = true; + EvaluateExpressionOptions expr_options; + expr_options.SetUnwindOnError(true); + expr_options.SetIgnoreBreakpoints(true); + expr_options.SetExecutionPolicy(eExecutionPolicyAlways); StreamString expr; expr.Printf("dlclose ((void *)0x%" PRIx64 ")", image_addr); const char *prefix = "extern \"C\" int dlclose(void* handle);\n"; lldb::ValueObjectSP result_valobj_sp; + Error expr_error; ClangUserExpression::Evaluate (exe_ctx, - eExecutionPolicyAlways, - lldb::eLanguageTypeUnknown, - ClangUserExpression::eResultTypeAny, - unwind_on_error, - ignore_breakpoints, + expr_options, expr.GetData(), prefix, result_valobj_sp, - true, - ClangUserExpression::kDefaultTimeout); + expr_error); if (result_valobj_sp->GetError().Success()) { Scalar scalar; @@ -2072,11 +2095,21 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw bp_site_sp.reset (new BreakpointSite (&m_breakpoint_site_list, owner, load_addr, use_hardware)); if (bp_site_sp) { - if (EnableBreakpointSite (bp_site_sp.get()).Success()) + Error error = EnableBreakpointSite (bp_site_sp.get()); + if (error.Success()) { owner->SetBreakpointSite (bp_site_sp); return m_breakpoint_site_list.Add (bp_site_sp); } + 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"); + } } } } @@ -2722,8 +2755,8 @@ Process::AllocateMemory(size_t size, uint32_t permissions, Error &error) addr_t allocated_addr = DoAllocateMemory (size, permissions, error); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); if (log) - log->Printf("Process::AllocateMemory(size=%4zu, permissions=%s) => 0x%16.16" PRIx64 " (m_stop_id = %u m_memory_id = %u)", - size, + log->Printf("Process::AllocateMemory(size=%" PRIu64 ", permissions=%s) => 0x%16.16" PRIx64 " (m_stop_id = %u m_memory_id = %u)", + (uint64_t)size, GetPermissionsAsCString (permissions), (uint64_t)allocated_addr, m_mod_id.GetStopID(), @@ -2845,6 +2878,7 @@ Process::Launch (const ProcessLaunchInfo &launch_info) Error error; m_abi_sp.reset(); m_dyld_ap.reset(); + m_system_runtime_ap.reset(); m_os_ap.reset(); m_process_input_reader.reset(); @@ -2913,6 +2947,10 @@ Process::Launch (const ProcessLaunchInfo &launch_info) if (dyld) dyld->DidLaunch(); + SystemRuntime *system_runtime = GetSystemRuntime (); + if (system_runtime) + system_runtime->DidLaunch(); + m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL)); // This delays passing the stopped event to listeners till DidLaunch gets // a chance to complete... @@ -2956,6 +2994,10 @@ Process::LoadCore () if (dyld) dyld->DidAttach(); + SystemRuntime *system_runtime = GetSystemRuntime (); + if (system_runtime) + system_runtime->DidAttach(); + m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL)); // We successfully loaded a core file, now pretend we stopped so we can // show all of the threads in the core file and explore the crashed @@ -2974,6 +3016,14 @@ Process::GetDynamicLoader () return m_dyld_ap.get(); } +SystemRuntime * +Process::GetSystemRuntime () +{ + if (m_system_runtime_ap.get() == NULL) + m_system_runtime_ap.reset (SystemRuntime::FindPlugin(this)); + return m_system_runtime_ap.get(); +} + Process::NextEventAction::EventActionResult Process::AttachCompletionHandler::PerformAction (lldb::EventSP &event_sp) @@ -3036,6 +3086,7 @@ Process::Attach (ProcessAttachInfo &attach_info) m_abi_sp.reset(); m_process_input_reader.reset(); m_dyld_ap.reset(); + m_system_runtime_ap.reset(); m_os_ap.reset(); lldb::pid_t attach_pid = attach_info.GetProcessID(); @@ -3208,6 +3259,10 @@ Process::CompleteAttach () if (dyld) dyld->DidAttach(); + SystemRuntime *system_runtime = GetSystemRuntime (); + if (system_runtime) + system_runtime->DidAttach(); + m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL)); // Figure out which one is the executable, and set that in our target: const ModuleList &target_modules = m_target.GetImages(); @@ -3968,15 +4023,15 @@ Process::HandlePrivateEvent (EventSP &event_sp) m_currently_handling_event.SetValue(false, eBroadcastAlways); } -void * +thread_result_t Process::PrivateStateThread (void *arg) { Process *proc = static_cast<Process*> (arg); - void *result = proc->RunPrivateStateThread (); + thread_result_t result = proc->RunPrivateStateThread(); return result; } -void * +thread_result_t Process::RunPrivateStateThread () { bool control_only = true; @@ -5095,15 +5150,15 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, uint64_t remaining_time = final_timeout - TimeValue::Now(); if (before_first_timeout) log->Printf ("Process::RunThreadPlan(): Running function with one thread timeout timed out, " - "running till for %" PRId64 " usec with all threads enabled.", + "running till for %" PRIu64 " usec with all threads enabled.", remaining_time); else log->Printf ("Process::RunThreadPlan(): Restarting function with all threads enabled " - "and timeout: %d timed out, abandoning execution.", + "and timeout: %u timed out, abandoning execution.", timeout_usec); } else - log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, " + log->Printf ("Process::RunThreadPlan(): Running function with timeout: %u timed out, " "abandoning execution.", timeout_usec); } @@ -5349,7 +5404,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, log->Printf("Process::RunThreadPlan(): execution interrupted: %s", s.GetData()); } - if (should_unwind && thread_plan_sp) + if (should_unwind) { if (log) log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.", thread_plan_sp.get()); @@ -5367,7 +5422,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, if (log) log->PutCString("Process::RunThreadPlan(): execution set up error."); - if (unwind_on_error && thread_plan_sp) + if (unwind_on_error) { thread->DiscardThreadPlansUpToPlan (thread_plan_sp); thread_plan_sp->SetPrivate (orig_plan_private); @@ -5578,11 +5633,10 @@ Process::DidExec () { Target &target = GetTarget(); target.CleanupProcess (); - ModuleList unloaded_modules (target.GetImages()); - target.ModulesDidUnload (unloaded_modules); - target.GetSectionLoadList().Clear(); + target.ClearModules(); m_dynamic_checkers_ap.reset(); m_abi_sp.reset(); + m_system_runtime_ap.reset(); m_os_ap.reset(); m_dyld_ap.reset(); m_image_tokens.clear(); @@ -5592,4 +5646,8 @@ Process::DidExec () m_memory_cache.Clear(true); DoDidExec(); CompleteAttach (); + // Flush the process (threads and all stack frames) after running CompleteAttach() + // in case the dynamic loader loaded things in new locations. + Flush(); } + diff --git a/contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp b/contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp index 0d89db7..3d68ba8 100644 --- a/contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp +++ b/contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp @@ -81,6 +81,15 @@ RegisterContext::GetRegisterInfoByName (const char *reg_name, uint32_t start_idx return NULL; } +const RegisterInfo * +RegisterContext::GetRegisterInfo (uint32_t kind, uint32_t num) +{ + const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num); + if (reg_num == LLDB_INVALID_REGNUM) + return NULL; + return GetRegisterInfoAtIndex (reg_num); +} + const char * RegisterContext::GetRegisterName (uint32_t reg) { @@ -113,6 +122,19 @@ RegisterContext::SetPC(uint64_t pc) return success; } +bool +RegisterContext::SetPC(Address addr) +{ + TargetSP target_sp = m_thread.CalculateTarget(); + Target *target = target_sp.get(); + + lldb::addr_t callAddr = addr.GetCallableLoadAddress (target); + if (callAddr == LLDB_INVALID_ADDRESS) + return false; + + return SetPC (callAddr); +} + uint64_t RegisterContext::GetSP(uint64_t fail_value) { diff --git a/contrib/llvm/tools/lldb/source/Target/StackFrame.cpp b/contrib/llvm/tools/lldb/source/Target/StackFrame.cpp index 3c4c43d..a936a57 100644 --- a/contrib/llvm/tools/lldb/source/Target/StackFrame.cpp +++ b/contrib/llvm/tools/lldb/source/Target/StackFrame.cpp @@ -48,7 +48,11 @@ StackFrame::StackFrame (const ThreadSP &thread_sp, user_id_t frame_idx, user_id_t unwind_frame_index, addr_t cfa, + bool cfa_is_valid, addr_t pc, + uint32_t stop_id, + bool stop_id_is_valid, + bool is_history_frame, const SymbolContext *sc_ptr) : m_thread_wp (thread_sp), m_frame_index (frame_idx), @@ -60,10 +64,21 @@ StackFrame::StackFrame (const ThreadSP &thread_sp, m_flags (), m_frame_base (), m_frame_base_error (), + m_cfa_is_valid (cfa_is_valid), + m_stop_id (stop_id), + m_stop_id_is_valid (stop_id_is_valid), + m_is_history_frame (is_history_frame), m_variable_list_sp (), m_variable_list_value_objects (), m_disassembly () { + // If we don't have a CFA value, use the frame index for our StackID so that recursive + // functions properly aren't confused with one another on a history stack. + if (m_is_history_frame && m_cfa_is_valid == false) + { + m_id.SetCFA (m_frame_index); + } + if (sc_ptr != NULL) { m_sc = *sc_ptr; @@ -88,6 +103,10 @@ StackFrame::StackFrame (const ThreadSP &thread_sp, m_flags (), m_frame_base (), m_frame_base_error (), + m_cfa_is_valid (true), + m_stop_id (0), + m_stop_id_is_valid (false), + m_is_history_frame (false), m_variable_list_sp (), m_variable_list_value_objects (), m_disassembly () @@ -123,6 +142,10 @@ StackFrame::StackFrame (const ThreadSP &thread_sp, m_flags (), m_frame_base (), m_frame_base_error (), + m_cfa_is_valid (true), + m_stop_id (0), + m_stop_id_is_valid (false), + m_is_history_frame (false), m_variable_list_sp (), m_variable_list_value_objects (), m_disassembly () @@ -246,15 +269,19 @@ StackFrame::GetFrameCodeAddress() return m_frame_code_addr; } -void +bool StackFrame::ChangePC (addr_t pc) { + // We can't change the pc value of a history stack frame - it is immutable. + if (m_is_history_frame) + return false; m_frame_code_addr.SetRawAddress(pc); m_sc.Clear(false); m_flags.Reset(0); ThreadSP thread_sp (GetThread()); if (thread_sp) thread_sp->ClearStackFrames (); + return true; } const char * @@ -517,6 +544,10 @@ StackFrame::GetVariableList (bool get_file_globals) VariableListSP StackFrame::GetInScopeVariableList (bool get_file_globals) { + // We can't fetch variable information for a history stack frame. + if (m_is_history_frame) + return VariableListSP(); + VariableListSP var_list_sp(new VariableList); GetSymbolContext (eSymbolContextCompUnit | eSymbolContextBlock); @@ -549,6 +580,9 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, VariableSP &var_sp, Error &error) { + // We can't fetch variable information for a history stack frame. + if (m_is_history_frame) + return ValueObjectSP(); if (var_expr_cstr && var_expr_cstr[0]) { @@ -1108,6 +1142,12 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, bool StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr) { + if (m_cfa_is_valid == false) + { + m_frame_base_error.SetErrorString("No frame base available for this historical stack frame."); + return false; + } + if (m_flags.IsClear(GOT_FRAME_BASE)) { if (m_sc.function) @@ -1172,6 +1212,10 @@ ValueObjectSP StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic) { ValueObjectSP valobj_sp; + if (m_is_history_frame) + { + return valobj_sp; + } VariableList *var_list = GetVariableList (true); if (var_list) { @@ -1202,6 +1246,9 @@ StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, Dynam ValueObjectSP StackFrame::TrackGlobalVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic) { + if (m_is_history_frame) + return ValueObjectSP(); + // Check to make sure we aren't already tracking this variable? ValueObjectSP valobj_sp (GetValueObjectForFrameVariable (variable_sp, use_dynamic)); if (!valobj_sp) @@ -1275,7 +1322,7 @@ StackFrame::CalculateExecutionContext (ExecutionContext &exe_ctx) } void -StackFrame::DumpUsingSettingsFormat (Stream *strm) +StackFrame::DumpUsingSettingsFormat (Stream *strm, const char *frame_marker) { if (strm == NULL) return; @@ -1283,6 +1330,10 @@ StackFrame::DumpUsingSettingsFormat (Stream *strm) GetSymbolContext(eSymbolContextEverything); ExecutionContext exe_ctx (shared_from_this()); StreamString s; + + if (frame_marker) + s.PutCString(frame_marker); + const char *frame_format = NULL; Target *target = exe_ctx.GetTargetPtr(); if (target) @@ -1370,13 +1421,14 @@ StackFrame::HasCachedData () const bool StackFrame::GetStatus (Stream& strm, bool show_frame_info, - bool show_source) + bool show_source, + const char *frame_marker) { if (show_frame_info) { strm.Indent(); - DumpUsingSettingsFormat (&strm); + DumpUsingSettingsFormat (&strm, frame_marker); } if (show_source) diff --git a/contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp b/contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp index 69309df..eaac361 100644 --- a/contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp +++ b/contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp @@ -336,7 +336,10 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx) SetAllFramesFetched(); break; } - unwind_frame_sp.reset (new StackFrame (m_thread.shared_from_this(), m_frames.size(), idx, cfa, pc, NULL)); + const bool cfa_is_valid = true; + const bool stop_id_is_valid = false; + const bool is_history_frame = false; + unwind_frame_sp.reset (new StackFrame (m_thread.shared_from_this(), m_frames.size(), idx, cfa, cfa_is_valid, pc, 0, stop_id_is_valid, is_history_frame, NULL)); m_frames.push_back (unwind_frame_sp); } @@ -534,7 +537,10 @@ StackFrameList::GetFrameAtIndex (uint32_t idx) addr_t pc, cfa; if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) { - frame_sp.reset (new StackFrame (m_thread.shared_from_this(), idx, idx, cfa, pc, NULL)); + const bool cfa_is_valid = true; + const bool stop_id_is_valid = false; + const bool is_history_frame = false; + frame_sp.reset (new StackFrame (m_thread.shared_from_this(), idx, idx, cfa, cfa_is_valid, pc, 0, stop_id_is_valid, is_history_frame, NULL)); Function *function = frame_sp->GetSymbolContext (eSymbolContextFunction).function; if (function) @@ -863,7 +869,8 @@ StackFrameList::GetStatus (Stream& strm, uint32_t first_frame, uint32_t num_frames, bool show_frame_info, - uint32_t num_frames_with_source) + uint32_t num_frames_with_source, + const char *selected_frame_marker) { size_t num_frames_displayed = 0; @@ -880,15 +887,34 @@ StackFrameList::GetStatus (Stream& strm, else last_frame = first_frame + num_frames; + StackFrameSP selected_frame_sp = m_thread.GetSelectedFrame(); + const char *unselected_marker = NULL; + std::string buffer; + if (selected_frame_marker) + { + size_t len = strlen(selected_frame_marker); + buffer.insert(buffer.begin(), len, ' '); + unselected_marker = buffer.c_str(); + } + const char *marker = NULL; + for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx) { frame_sp = GetFrameAtIndex(frame_idx); if (frame_sp.get() == NULL) break; + if (selected_frame_marker != NULL) + { + if (frame_sp == selected_frame_sp) + marker = selected_frame_marker; + else + marker = unselected_marker; + } + if (!frame_sp->GetStatus (strm, show_frame_info, - num_frames_with_source > (first_frame - frame_idx))) + num_frames_with_source > (first_frame - frame_idx), marker)) break; ++num_frames_displayed; } diff --git a/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp b/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp index 81b9d86..914969a 100644 --- a/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp +++ b/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp @@ -694,22 +694,17 @@ protected: // We need to make sure the user sees any parse errors in their condition, so we'll hook the // constructor errors up to the debugger's Async I/O. ExecutionResults result_code; + EvaluateExpressionOptions expr_options; + expr_options.SetUnwindOnError(true); + expr_options.SetIgnoreBreakpoints(true); ValueObjectSP result_value_sp; - const bool unwind_on_error = true; - const bool ignore_breakpoints = true; Error error; - result_code = ClangUserExpression::EvaluateWithError (exe_ctx, - eExecutionPolicyOnlyWhenNeeded, - lldb::eLanguageTypeUnknown, - ClangUserExpression::eResultTypeAny, - unwind_on_error, - ignore_breakpoints, - wp_sp->GetConditionText(), - NULL, - result_value_sp, - error, - true, - ClangUserExpression::kDefaultTimeout); + result_code = ClangUserExpression::Evaluate (exe_ctx, + expr_options, + wp_sp->GetConditionText(), + NULL, + result_value_sp, + error); if (result_code == eExecutionCompleted) { if (result_value_sp) diff --git a/contrib/llvm/tools/lldb/source/Target/SystemRuntime.cpp b/contrib/llvm/tools/lldb/source/Target/SystemRuntime.cpp new file mode 100644 index 0000000..7ce150f --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Target/SystemRuntime.cpp @@ -0,0 +1,73 @@ +//===-- SystemRuntime.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-private.h" +#include "lldb/Target/SystemRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Core/PluginManager.h" + +using namespace lldb; +using namespace lldb_private; + +SystemRuntime* +SystemRuntime::FindPlugin (Process *process) +{ + SystemRuntimeCreateInstance create_callback = NULL; + for (uint32_t idx = 0; (create_callback = PluginManager::GetSystemRuntimeCreateCallbackAtIndex(idx)) != NULL; ++idx) + { + std::unique_ptr<SystemRuntime> instance_ap(create_callback(process)); + if (instance_ap.get()) + return instance_ap.release(); + } + return NULL; +} + + +//---------------------------------------------------------------------- +// SystemRuntime constructor +//---------------------------------------------------------------------- +SystemRuntime::SystemRuntime(Process *process) : + m_process (process) +{ +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +SystemRuntime::~SystemRuntime() +{ +} + +void +SystemRuntime::DidAttach () +{ +} + +void +SystemRuntime::DidLaunch() +{ +} + +void +SystemRuntime::ModulesDidLoad (ModuleList &module_list) +{ +} + +std::vector<ConstString> +SystemRuntime::GetExtendedBacktraceTypes () +{ + std::vector<ConstString> types; + return types; +} + +ThreadSP +SystemRuntime::GetExtendedBacktrace (ThreadSP thread, ConstString type) +{ + return ThreadSP(); +} diff --git a/contrib/llvm/tools/lldb/source/Target/Target.cpp b/contrib/llvm/tools/lldb/source/Target/Target.cpp index 5766b73..18efd8c 100644 --- a/contrib/llvm/tools/lldb/source/Target/Target.cpp +++ b/contrib/llvm/tools/lldb/source/Target/Target.cpp @@ -43,6 +43,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" +#include "lldb/Target/SystemRuntime.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadSpec.h" @@ -83,8 +84,7 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat m_source_manager_ap(), m_stop_hooks (), m_stop_hook_next_id (0), - m_suppress_stop_hooks (false), - m_suppress_synthetic_value(false) + m_suppress_stop_hooks (false) { SetEventName (eBroadcastBitBreakpointChanged, "breakpoint-changed"); SetEventName (eBroadcastBitModulesLoaded, "modules-loaded"); @@ -192,7 +192,7 @@ Target::Destroy() DeleteCurrentProcess (); m_platform_sp.reset(); m_arch.Clear(); - m_images.Clear(); + ClearModules(); m_section_load_list.Clear(); const bool notify = false; m_breakpoint_list.RemoveAll(notify); @@ -201,14 +201,10 @@ Target::Destroy() m_last_created_watchpoint.reset(); m_search_filter_sp.reset(); m_image_search_paths.Clear(notify); - m_scratch_ast_context_ap.reset(); - m_scratch_ast_source_ap.reset(); - m_ast_importer_ap.reset(); m_persistent_variables.Clear(); m_stop_hooks.clear(); m_stop_hook_next_id = 0; m_suppress_stop_hooks = false; - m_suppress_synthetic_value = false; } @@ -247,11 +243,12 @@ BreakpointSP Target::CreateSourceRegexBreakpoint (const FileSpecList *containingModules, const FileSpecList *source_file_spec_list, RegularExpression &source_regex, - bool internal) + bool internal, + bool hardware) { SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, source_file_spec_list)); BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex (NULL, source_regex)); - return CreateBreakpoint (filter_sp, resolver_sp, internal); + return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware); } @@ -261,7 +258,8 @@ Target::CreateBreakpoint (const FileSpecList *containingModules, uint32_t line_no, LazyBool check_inlines, LazyBool skip_prologue, - bool internal) + bool internal, + bool hardware) { if (check_inlines == eLazyBoolCalculate) { @@ -304,12 +302,12 @@ Target::CreateBreakpoint (const FileSpecList *containingModules, line_no, check_inlines, skip_prologue)); - return CreateBreakpoint (filter_sp, resolver_sp, internal); + return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware); } BreakpointSP -Target::CreateBreakpoint (lldb::addr_t addr, bool internal) +Target::CreateBreakpoint (lldb::addr_t addr, bool internal, bool hardware) { Address so_addr; // Attempt to resolve our load address if possible, though it is ok if @@ -322,16 +320,16 @@ Target::CreateBreakpoint (lldb::addr_t addr, bool internal) // The address didn't resolve, so just set this as an absolute address so_addr.SetOffset (addr); } - BreakpointSP bp_sp (CreateBreakpoint(so_addr, internal)); + BreakpointSP bp_sp (CreateBreakpoint(so_addr, internal, hardware)); return bp_sp; } BreakpointSP -Target::CreateBreakpoint (Address &addr, bool internal) +Target::CreateBreakpoint (Address &addr, bool internal, bool hardware) { SearchFilterSP filter_sp(new SearchFilterForNonModuleSpecificSearches (shared_from_this())); BreakpointResolverSP resolver_sp (new BreakpointResolverAddress (NULL, addr)); - return CreateBreakpoint (filter_sp, resolver_sp, internal); + return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware); } BreakpointSP @@ -340,7 +338,8 @@ Target::CreateBreakpoint (const FileSpecList *containingModules, const char *func_name, uint32_t func_name_type_mask, LazyBool skip_prologue, - bool internal) + bool internal, + bool hardware) { BreakpointSP bp_sp; if (func_name) @@ -355,7 +354,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules, func_name_type_mask, Breakpoint::Exact, skip_prologue)); - bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal); + bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware); } return bp_sp; } @@ -366,7 +365,8 @@ Target::CreateBreakpoint (const FileSpecList *containingModules, const std::vector<std::string> &func_names, uint32_t func_name_type_mask, LazyBool skip_prologue, - bool internal) + bool internal, + bool hardware) { BreakpointSP bp_sp; size_t num_names = func_names.size(); @@ -381,7 +381,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules, func_names, func_name_type_mask, skip_prologue)); - bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal); + bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware); } return bp_sp; } @@ -393,7 +393,8 @@ Target::CreateBreakpoint (const FileSpecList *containingModules, size_t num_names, uint32_t func_name_type_mask, LazyBool skip_prologue, - bool internal) + bool internal, + bool hardware) { BreakpointSP bp_sp; if (num_names > 0) @@ -408,7 +409,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules, num_names, func_name_type_mask, skip_prologue)); - bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal); + bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware); } return bp_sp; } @@ -478,14 +479,15 @@ Target::CreateFuncRegexBreakpoint (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles, RegularExpression &func_regex, LazyBool skip_prologue, - bool internal) + bool internal, + bool hardware) { SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, containingSourceFiles)); BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL, func_regex, skip_prologue == eLazyBoolCalculate ? GetSkipPrologue() : skip_prologue)); - return CreateBreakpoint (filter_sp, resolver_sp, internal); + return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware); } lldb::BreakpointSP @@ -495,12 +497,12 @@ Target::CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_ } BreakpointSP -Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool internal) +Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool internal, bool request_hardware) { BreakpointSP bp_sp; if (filter_sp && resolver_sp) { - bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp)); + bp_sp.reset(new Breakpoint (*this, filter_sp, resolver_sp, request_hardware)); resolver_sp->SetBreakpoint (bp_sp.get()); if (internal) @@ -630,7 +632,7 @@ Target::CreateWatchpoint(lldb::addr_t addr, size_t size, const ClangASTType *typ if (!CheckIfWatchpointsExhausted(this, error)) { if (!OptionGroupWatchpoint::IsWatchSizeSupported(size)) - error.SetErrorStringWithFormat("watch size of %lu is not supported", size); + error.SetErrorStringWithFormat("watch size of %zu is not supported", size); } wp_sp.reset(); } @@ -1012,13 +1014,21 @@ LoadScriptingResourceForModule (const ModuleSP &module_sp, Target *target) } void -Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files) +Target::ClearModules() { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TARGET)); + ModulesDidUnload (m_images, true); + GetSectionLoadList().Clear(); m_images.Clear(); m_scratch_ast_context_ap.reset(); m_scratch_ast_source_ap.reset(); m_ast_importer_ap.reset(); +} + +void +Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TARGET)); + ClearModules(); if (executable_sp.get()) { @@ -1087,10 +1097,8 @@ Target::SetArchitecture (const ArchSpec &arch_spec) log->Printf ("Target::SetArchitecture changing architecture to %s (%s)", arch_spec.GetArchitectureName(), arch_spec.GetTriple().getTriple().c_str()); m_arch = arch_spec; ModuleSP executable_sp = GetExecutableModule (); - m_images.Clear(); - m_scratch_ast_context_ap.reset(); - m_scratch_ast_source_ap.reset(); - m_ast_importer_ap.reset(); + + ClearModules(); // Need to do something about unsetting breakpoints. if (executable_sp) @@ -1135,7 +1143,7 @@ Target::ModuleRemoved (const ModuleList& module_list, const ModuleSP &module_sp) // A module is being added to this target for the first time ModuleList my_module_list; my_module_list.Append(module_sp); - ModulesDidUnload (my_module_list); + ModulesDidUnload (my_module_list, false); } void @@ -1150,7 +1158,15 @@ Target::ModulesDidLoad (ModuleList &module_list) { if (module_list.GetSize()) { - m_breakpoint_list.UpdateBreakpoints (module_list, true); + m_breakpoint_list.UpdateBreakpoints (module_list, true, false); + if (m_process_sp) + { + SystemRuntime *sys_runtime = m_process_sp->GetSystemRuntime(); + if (sys_runtime) + { + sys_runtime->ModulesDidLoad (module_list); + } + } // TODO: make event data that packages up the module_list BroadcastEvent (eBroadcastBitModulesLoaded, NULL); } @@ -1171,17 +1187,17 @@ Target::SymbolsDidLoad (ModuleList &module_list) } } - m_breakpoint_list.UpdateBreakpoints (module_list, true); + m_breakpoint_list.UpdateBreakpoints (module_list, true, false); BroadcastEvent(eBroadcastBitSymbolsLoaded, NULL); } } void -Target::ModulesDidUnload (ModuleList &module_list) +Target::ModulesDidUnload (ModuleList &module_list, bool delete_locations) { if (module_list.GetSize()) { - m_breakpoint_list.UpdateBreakpoints (module_list, false); + m_breakpoint_list.UpdateBreakpoints (module_list, false, delete_locations); // TODO: make event data that packages up the module_list BroadcastEvent (eBroadcastBitModulesUnloaded, NULL); } @@ -1724,10 +1740,7 @@ Target::ImageSearchPathsChanged Target *target = (Target *)baton; ModuleSP exe_module_sp (target->GetExecutableModule()); if (exe_module_sp) - { - target->m_images.Clear(); target->SetExecutableModule (exe_module_sp, true); - } } ClangASTContext * @@ -1875,18 +1888,13 @@ Target::EvaluateExpression else { const char *prefix = GetExpressionPrefixContentsAsCString(); - + Error error; execution_results = ClangUserExpression::Evaluate (exe_ctx, - options.GetExecutionPolicy(), - lldb::eLanguageTypeUnknown, - options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny, - options.DoesUnwindOnError(), - options.DoesIgnoreBreakpoints(), - expr_cstr, + options, + expr_cstr, prefix, result_valobj_sp, - options.GetRunOthers(), - options.GetTimeoutUsec()); + error); } m_suppress_stop_hooks = old_suppress_value; diff --git a/contrib/llvm/tools/lldb/source/Target/TargetList.cpp b/contrib/llvm/tools/lldb/source/Target/TargetList.cpp index 8d907f4..c4da84f 100644 --- a/contrib/llvm/tools/lldb/source/Target/TargetList.cpp +++ b/contrib/llvm/tools/lldb/source/Target/TargetList.cpp @@ -363,7 +363,7 @@ TargetList::FindTargetWithExecutableAndArchitecture { Mutex::Locker locker (m_target_list_mutex); TargetSP target_sp; - bool full_match = exe_file_spec.GetDirectory(); + bool full_match = (bool)exe_file_spec.GetDirectory(); collection::const_iterator pos, end = m_target_list.end(); for (pos = m_target_list.begin(); pos != end; ++pos) diff --git a/contrib/llvm/tools/lldb/source/Target/Thread.cpp b/contrib/llvm/tools/lldb/source/Target/Thread.cpp index b65434b..98c2601 100644 --- a/contrib/llvm/tools/lldb/source/Target/Thread.cpp +++ b/contrib/llvm/tools/lldb/source/Target/Thread.cpp @@ -282,12 +282,18 @@ Thread::~Thread() void Thread::DestroyThread () { - // Tell any plans on the plan stack that the thread is being destroyed since - // any active plans that have a thread go away in the middle of might need - // to do cleanup. + // Tell any plans on the plan stacks that the thread is being destroyed since + // any plans that have a thread go away in the middle of might need + // to do cleanup, or in some cases NOT do cleanup... for (auto plan : m_plan_stack) plan->ThreadDestroyed(); + for (auto plan : m_discarded_plan_stack) + plan->ThreadDestroyed(); + + for (auto plan : m_completed_plan_stack) + plan->ThreadDestroyed(); + m_destroy_called = true; m_plan_stack.clear(); m_discarded_plan_stack.clear(); @@ -1745,6 +1751,79 @@ Thread::ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return return return_error; } +static void DumpAddressList (Stream &s, const std::vector<Address> &list, ExecutionContextScope *exe_scope) +{ + for (size_t n=0;n<list.size();n++) + { + s << "\t"; + list[n].Dump (&s, exe_scope, Address::DumpStyleResolvedDescription, Address::DumpStyleSectionNameOffset); + s << "\n"; + } +} + +Error +Thread::JumpToLine (const FileSpec &file, uint32_t line, bool can_leave_function, std::string *warnings) +{ + ExecutionContext exe_ctx (GetStackFrameAtIndex(0)); + Target *target = exe_ctx.GetTargetPtr(); + TargetSP target_sp = exe_ctx.GetTargetSP(); + RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); + StackFrame *frame = exe_ctx.GetFramePtr(); + const SymbolContext &sc = frame->GetSymbolContext(eSymbolContextFunction); + + // Find candidate locations. + std::vector<Address> candidates, within_function, outside_function; + target->GetImages().FindAddressesForLine (target_sp, file, line, sc.function, within_function, outside_function); + + // If possible, we try and stay within the current function. + // Within a function, we accept multiple locations (optimized code may do this, + // there's no solution here so we do the best we can). + // However if we're trying to leave the function, we don't know how to pick the + // right location, so if there's more than one then we bail. + if (!within_function.empty()) + candidates = within_function; + else if (outside_function.size() == 1 && can_leave_function) + candidates = outside_function; + + // Check if we got anything. + if (candidates.empty()) + { + if (outside_function.empty()) + { + return Error("Cannot locate an address for %s:%i.", + file.GetFilename().AsCString(), line); + } + else if (outside_function.size() == 1) + { + return Error("%s:%i is outside the current function.", + file.GetFilename().AsCString(), line); + } + else + { + StreamString sstr; + DumpAddressList(sstr, outside_function, target); + return Error("%s:%i has multiple candidate locations:\n%s", + file.GetFilename().AsCString(), line, sstr.GetString().c_str()); + } + } + + // Accept the first location, warn about any others. + Address dest = candidates[0]; + if (warnings && candidates.size() > 1) + { + StreamString sstr; + sstr.Printf("%s:%i appears multiple times in this function, selecting the first location:\n", + file.GetFilename().AsCString(), line); + DumpAddressList(sstr, candidates, target); + *warnings = sstr.GetString(); + } + + if (!reg_ctx->SetPC (dest)) + return Error("Cannot change PC to target address."); + + return Error(); +} + void Thread::DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx) { @@ -1784,6 +1863,24 @@ Thread::SettingsTerminate () { } +lldb::addr_t +Thread::GetThreadPointer () +{ + return LLDB_INVALID_ADDRESS; +} + +addr_t +Thread::GetThreadLocalData (const ModuleSP module) +{ + // The default implementation is to ask the dynamic loader for it. + // This can be overridden for specific platforms. + DynamicLoader *loader = GetProcess()->GetDynamicLoader(); + if (loader) + return loader->GetThreadLocalData (module, shared_from_this()); + else + return LLDB_INVALID_ADDRESS; +} + lldb::StackFrameSP Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr) { @@ -1863,13 +1960,21 @@ Thread::GetStatus (Stream &strm, uint32_t start_frame, uint32_t num_frames, uint strm.IndentMore(); const bool show_frame_info = true; - strm.IndentMore (); + + const char *selected_frame_marker = NULL; + if (num_frames == 1 || (GetID() != GetProcess()->GetThreadList().GetSelectedThread()->GetID())) + strm.IndentMore (); + else + selected_frame_marker = "* "; + num_frames_shown = GetStackFrameList ()->GetStatus (strm, start_frame, num_frames, show_frame_info, - num_frames_with_source); - strm.IndentLess(); + num_frames_with_source, + selected_frame_marker); + if (num_frames == 1) + strm.IndentLess(); strm.IndentLess(); } return num_frames_shown; @@ -1944,6 +2049,7 @@ Thread::GetUnwinder () case llvm::Triple::x86: case llvm::Triple::arm: case llvm::Triple::thumb: + case llvm::Triple::mips64: m_unwinder_ap.reset (new UnwindLLDB (*this)); break; diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp index 86825d2..9e77139 100644 --- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp +++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp @@ -88,7 +88,7 @@ ThreadPlanRunToAddress::SetInitialBreakpoints () for (size_t i = 0; i < num_addresses; i++) { Breakpoint *breakpoint; - breakpoint = m_thread.CalculateTarget()->CreateBreakpoint (m_addresses[i], true).get(); + breakpoint = m_thread.CalculateTarget()->CreateBreakpoint (m_addresses[i], true, false).get(); if (breakpoint != NULL) { m_break_ids[i] = breakpoint->GetID(); diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp index ba52958..c5efb55 100644 --- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp +++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp @@ -102,7 +102,7 @@ ThreadPlanStepOut::ThreadPlanStepOut if (m_return_addr == LLDB_INVALID_ADDRESS) return; - Breakpoint *return_bp = m_thread.CalculateTarget()->CreateBreakpoint (m_return_addr, true).get(); + Breakpoint *return_bp = m_thread.CalculateTarget()->CreateBreakpoint (m_return_addr, true, false).get(); if (return_bp != NULL) { return_bp->SetThreadID(m_thread.GetID()); diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp index 7b8539c..2d8108b 100644 --- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp +++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp @@ -66,6 +66,32 @@ ThreadPlanStepOverRange::GetDescription (Stream *s, lldb::DescriptionLevel level } bool +ThreadPlanStepOverRange::IsEquivalentContext(const SymbolContext &context) +{ + + // Match as much as is specified in the m_addr_context: + // This is a fairly loose sanity check. Note, sometimes the target doesn't get filled + // in so I left out the target check. And sometimes the module comes in as the .o file from the + // inlined range, so I left that out too... + if (m_addr_context.comp_unit) + { + if (m_addr_context.comp_unit == context.comp_unit) + { + if (m_addr_context.function && m_addr_context.function == context.function) + { + if (m_addr_context.block && m_addr_context.block == context.block) + return true; + } + } + } + else if (m_addr_context.symbol && m_addr_context.symbol == context.symbol) + { + return true; + } + return false; +} + +bool ThreadPlanStepOverRange::ShouldStop (Event *event_ptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); @@ -109,51 +135,29 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr) { // Make sure we really are in a new frame. Do that by unwinding and seeing if the // start function really is our start function... - StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(1); - - // But if we can't even unwind one frame we should just get out of here & stop... - if (older_frame_sp) + for(uint32_t i = 1;; ++i) { - const SymbolContext &older_context = older_frame_sp->GetSymbolContext(eSymbolContextEverything); - - // Match as much as is specified in the m_addr_context: - // This is a fairly loose sanity check. Note, sometimes the target doesn't get filled - // in so I left out the target check. And sometimes the module comes in as the .o file from the - // inlined range, so I left that out too... - - bool older_ctx_is_equivalent = true; - if (m_addr_context.comp_unit) - { - if (m_addr_context.comp_unit == older_context.comp_unit) - { - if (m_addr_context.function && m_addr_context.function == older_context.function) - { - if (m_addr_context.block && m_addr_context.block == older_context.block) - { - older_ctx_is_equivalent = true; - } - } - } - } - else if (m_addr_context.symbol && m_addr_context.symbol == older_context.symbol) - { - older_ctx_is_equivalent = true; + StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(i); + if (!older_frame_sp) { + // We can't unwind the next frame we should just get out of here & stop... + break; } - - if (older_ctx_is_equivalent) + + const SymbolContext &older_context = older_frame_sp->GetSymbolContext(eSymbolContextEverything); + if (IsEquivalentContext(older_context)) { new_plan_sp = m_thread.QueueThreadPlanForStepOut (false, - NULL, - true, - stop_others, - eVoteNo, + NULL, + true, + stop_others, + eVoteNo, eVoteNoOpinion, 0); + break; } - else + else { new_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); - } } } diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp index 3940d54..309f773 100644 --- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp +++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp @@ -173,6 +173,25 @@ ThreadPlanStepRange::InRange () log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData()); } } + else if (new_context.line_entry.line == 0) + { + new_context.line_entry.line = m_addr_context.line_entry.line; + m_addr_context = new_context; + AddRange(m_addr_context.line_entry.range); + ret_value = true; + if (log) + { + StreamString s; + m_addr_context.line_entry.Dump (&s, + m_thread.CalculateTarget().get(), + true, + Address::DumpStyleLoadAddress, + Address::DumpStyleLoadAddress, + true); + + log->Printf ("Step range plan stepped to a range at linenumber 0 stepping through that range: %s", s.GetData()); + } + } else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(m_thread.CalculateTarget().get()) != pc_load_addr) { @@ -284,11 +303,13 @@ ThreadPlanStepRange::GetInstructionsForAddress(lldb::addr_t addr, size_t &range_ ExecutionContext exe_ctx (m_thread.GetProcess()); const char *plugin_name = NULL; const char *flavor = NULL; + const bool prefer_file_cache = true; m_instruction_ranges[i] = Disassembler::DisassembleRange(GetTarget().GetArchitecture(), plugin_name, flavor, exe_ctx, - m_address_ranges[i]); + m_address_ranges[i], + prefer_file_cache); } if (!m_instruction_ranges[i]) @@ -361,7 +382,7 @@ ThreadPlanStepRange::SetNextBranchBreakpoint () { const bool is_internal = true; run_to_address = instructions->GetInstructionAtIndex(branch_index)->GetAddress(); - m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal); + m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal, false); if (m_next_branch_bp_sp) { if (log) diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp index 92d1fcd..37cd03c 100644 --- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp +++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp @@ -56,7 +56,7 @@ ThreadPlanStepThrough::ThreadPlanStepThrough (Thread &thread, StackID &m_stack_i if (return_frame_sp) { m_backstop_addr = return_frame_sp->GetFrameCodeAddress().GetLoadAddress(m_thread.CalculateTarget().get()); - Breakpoint *return_bp = m_thread.GetProcess()->GetTarget().CreateBreakpoint (m_backstop_addr, true).get(); + Breakpoint *return_bp = m_thread.GetProcess()->GetTarget().CreateBreakpoint (m_backstop_addr, true, false).get(); if (return_bp != NULL) { return_bp->SetThreadID(m_thread.GetID()); diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp index e1b5a05..62e05c7 100644 --- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp +++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp @@ -68,7 +68,7 @@ ThreadPlanStepUntil::ThreadPlanStepUntil { // TODO: add inline functionality m_return_addr = return_frame_sp->GetStackID().GetPC(); - Breakpoint *return_bp = target_sp->CreateBreakpoint (m_return_addr, true).get(); + Breakpoint *return_bp = target_sp->CreateBreakpoint (m_return_addr, true, false).get(); if (return_bp != NULL) { return_bp->SetThreadID(thread_id); @@ -82,7 +82,7 @@ ThreadPlanStepUntil::ThreadPlanStepUntil // Now set breakpoints on all our return addresses: for (size_t i = 0; i < num_addresses; i++) { - Breakpoint *until_bp = target_sp->CreateBreakpoint (address_list[i], true).get(); + Breakpoint *until_bp = target_sp->CreateBreakpoint (address_list[i], true, false).get(); if (until_bp != NULL) { until_bp->SetThreadID(thread_id); diff --git a/contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp b/contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp index 7fe81f8..16a35b5 100644 --- a/contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp +++ b/contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp @@ -74,13 +74,13 @@ UnixSignals::Reset () AddSignal (11, "SIGSEGV", "SEGV", false, true , true , "segmentation violation"); AddSignal (12, "SIGSYS", "SYS", false, true , true , "bad argument to system call"); AddSignal (13, "SIGPIPE", "PIPE", false, true , true , "write on a pipe with no one to read it"); - AddSignal (14, "SIGALRM", "ALRM", false, false, true , "alarm clock"); + AddSignal (14, "SIGALRM", "ALRM", false, false, false, "alarm clock"); AddSignal (15, "SIGTERM", "TERM", false, true , true , "software termination signal from kill"); AddSignal (16, "SIGURG", "URG", false, false, false, "urgent condition on IO channel"); AddSignal (17, "SIGSTOP", "STOP", true , true , true , "sendable stop signal not from tty"); AddSignal (18, "SIGTSTP", "TSTP", false, true , true , "stop signal from tty"); AddSignal (19, "SIGCONT", "CONT", false, true , true , "continue a stopped process"); - AddSignal (20, "SIGCHLD", "CHLD", false, false, true , "to parent on child stop or exit"); + AddSignal (20, "SIGCHLD", "CHLD", false, false, false, "to parent on child stop or exit"); AddSignal (21, "SIGTTIN", "TTIN", false, true , true , "to readers process group upon background tty read"); AddSignal (22, "SIGTTOU", "TTOU", false, true , true , "to readers process group upon background tty write"); AddSignal (23, "SIGIO", "IO", false, false, false, "input/output possible signal"); |