diff options
| -rw-r--r-- | lldb/lldb.xcodeproj/project.pbxproj | 1 | ||||
| -rw-r--r-- | lldb/source/Host/macosx/Host.mm | 273 | ||||
| -rw-r--r-- | lldb/tools/darwin-debug/darwin-debug.cpp | 5 |
3 files changed, 190 insertions, 89 deletions
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index a0caa4a8d66..4c898f70714 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -2490,6 +2490,7 @@ isa = PBXProject; buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "lldb" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( en, diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm index b9f6235c5f5..e4227190a48 100644 --- a/lldb/source/Host/macosx/Host.mm +++ b/lldb/source/Host/macosx/Host.mm @@ -9,8 +9,10 @@ #include "lldb/Host/Host.h" -#include <sys/types.h> +#include <libproc.h> +#include <sys/proc.h> #include <sys/stat.h> +#include <sys/types.h> #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Communication.h" @@ -159,79 +161,15 @@ Host::LaunchApplication (const FileSpec &app_file_spec) error = ::GetProcessPID(&psn, &pid); return pid; } -#define LLDB_HOST_USE_APPLESCRIPT -#if defined (LLDB_HOST_USE_APPLESCRIPT) - -lldb::pid_t -Host::LaunchInNewTerminal -( - const char **argv, - const char **envp, - const ArchSpec *arch_spec, - bool stop_at_entry, - bool disable_aslr -) -{ - if (!argv || !argv[0]) - return LLDB_INVALID_PROCESS_ID; - - std::string unix_socket_name; - - char temp_file_path[PATH_MAX] = "/tmp/XXXXXX"; - if (::mktemp (temp_file_path) == NULL) - return LLDB_INVALID_PROCESS_ID; - - unix_socket_name.assign (temp_file_path); - - StreamString command; - - FileSpec darwin_debug_file_spec; - if (!Host::GetLLDBPath (ePathTypeSupportExecutableDir, darwin_debug_file_spec)) - return LLDB_INVALID_PROCESS_ID; - darwin_debug_file_spec.GetFilename().SetCString("darwin-debug"); - - if (!darwin_debug_file_spec.Exists()) - return LLDB_INVALID_PROCESS_ID; - - char launcher_path[PATH_MAX]; - darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path)); - command.Printf ("tell application \"Terminal\"\n do script \"'%s'", launcher_path); - - command.Printf(" --unix-socket=%s", unix_socket_name.c_str()); - - if (arch_spec && arch_spec->IsValid()) - { - command.Printf(" --arch=%s", arch_spec->AsCString()); - } - - if (disable_aslr) - { - command.PutCString(" --disable-aslr"); - } - - command.PutCString(" --"); - - if (argv) - { - for (size_t i=0; argv[i] != NULL; ++i) - { - command.Printf(" '%s'", argv[i]); - } - } - command.PutCString (" ; exit\"\nend tell\n"); - const char *script_source = command.GetString().c_str(); - NSAppleScript* applescript = [[NSAppleScript alloc] initWithSource:[NSString stringWithCString:script_source encoding:NSUTF8StringEncoding]]; - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; - Error lldb_error; - // Sleep and wait a bit for debugserver to start to listen... +static void * +AcceptPIDFromInferior (void *arg) +{ + const char *connect_url = (const char *)arg; ConnectionFileDescriptor file_conn; - char connect_url[128]; - ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name.c_str()); - - [applescript executeAndReturnError:nil]; - if (file_conn.Connect(connect_url, &lldb_error) == eConnectionStatusSuccess) + Error error; + if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess) { char pid_str[256]; ::bzero (pid_str, sizeof(pid_str)); @@ -239,18 +177,48 @@ Host::LaunchInNewTerminal const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), status, NULL); if (pid_str_len > 0) { - pid = atoi (pid_str); - // Sleep for a bit to allow the process to exec and stop at the entry point... - sleep(1); + int pid = atoi (pid_str); + return (void *)(intptr_t)pid; } } - [applescript release]; - return pid; + return NULL; } -#else -lldb::pid_t -Host::LaunchInNewTerminal +static bool +WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds) +{ + const int time_delta_usecs = 100000; + const int num_retries = timeout_in_seconds/time_delta_usecs; + for (int i=0; i<num_retries; i++) + { + struct proc_bsdinfo bsd_info; + int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO, + (uint64_t) 0, + &bsd_info, + PROC_PIDTBSDINFO_SIZE); + + switch (error) + { + case EINVAL: + case ENOTSUP: + case ESRCH: + case EPERM: + return false; + + default: + break; + + case 0: + if (bsd_info.pbi_status == SSTOP) + return true; + } + ::usleep (time_delta_usecs); + } + return false; +} + +static lldb::pid_t +LaunchInNewTerminalWithCommandFile ( const char **argv, const char **envp, @@ -365,31 +333,158 @@ Host::LaunchInNewTerminal Error lldb_error; // Sleep and wait a bit for debugserver to start to listen... - ConnectionFileDescriptor file_conn; char connect_url[128]; ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name.c_str()); + // Spawn a new thread to accept incoming connection on the connect_url + // so we can grab the pid from the inferior + lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name.c_str(), + AcceptPIDFromInferior, + connect_url, + &lldb_error); + ProcessSerialNumber psn; error = LSOpenURLsWithRole(urls.get(), kLSRolesShell, NULL, &app_params, &psn, 1); if (error == noErr) { - if (file_conn.Connect(connect_url, &lldb_error) == eConnectionStatusSuccess) + thread_result_t accept_thread_result = NULL; + if (Host::ThreadJoin (accept_thread, &accept_thread_result, &lldb_error)) { - char pid_str[256]; - ::bzero (pid_str, sizeof(pid_str)); - ConnectionStatus status; - const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), status, NULL); - if (pid_str_len > 0) + if (accept_thread_result) { - pid = atoi (pid_str); - // Sleep for a bit to allow the process to exec and stop at the entry point... - sleep(1); + pid = (intptr_t)accept_thread_result; + + // Wait for process to be stopped the the entry point by watching + // for the process status to be set to SSTOP which indicates it it + // SIGSTOP'ed at the entry point + WaitForProcessToSIGSTOP (pid, 5); } } } + else + { + Host::ThreadCancel (accept_thread, &lldb_error); + } + + return pid; +} + + +lldb::pid_t +LaunchInNewTerminalWithAppleScript +( + const char **argv, + const char **envp, + const ArchSpec *arch_spec, + bool stop_at_entry, + bool disable_aslr +) +{ + if (!argv || !argv[0]) + return LLDB_INVALID_PROCESS_ID; + + std::string unix_socket_name; + + char temp_file_path[PATH_MAX] = "/tmp/XXXXXX"; + if (::mktemp (temp_file_path) == NULL) + return LLDB_INVALID_PROCESS_ID; + + unix_socket_name.assign (temp_file_path); + + StreamString command; + + FileSpec darwin_debug_file_spec; + if (!Host::GetLLDBPath (ePathTypeSupportExecutableDir, darwin_debug_file_spec)) + return LLDB_INVALID_PROCESS_ID; + darwin_debug_file_spec.GetFilename().SetCString("darwin-debug"); + + if (!darwin_debug_file_spec.Exists()) + return LLDB_INVALID_PROCESS_ID; + + char launcher_path[PATH_MAX]; + darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path)); + command.Printf ("tell application \"Terminal\"\n do script \"'%s'", launcher_path); + + command.Printf(" --unix-socket=%s", unix_socket_name.c_str()); + + if (arch_spec && arch_spec->IsValid()) + { + command.Printf(" --arch=%s", arch_spec->AsCString()); + } + + if (disable_aslr) + { + command.PutCString(" --disable-aslr"); + } + + command.PutCString(" --"); + + if (argv) + { + for (size_t i=0; argv[i] != NULL; ++i) + { + command.Printf(" '%s'", argv[i]); + } + } + command.PutCString (" ; echo Process exited with status $?\"\nend tell\n"); + const char *script_source = command.GetString().c_str(); + NSAppleScript* applescript = [[NSAppleScript alloc] initWithSource:[NSString stringWithCString:script_source encoding:NSUTF8StringEncoding]]; + + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + + Error lldb_error; + // Sleep and wait a bit for debugserver to start to listen... + ConnectionFileDescriptor file_conn; + char connect_url[128]; + ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name.c_str()); + + // Spawn a new thread to accept incoming connection on the connect_url + // so we can grab the pid from the inferior + lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name.c_str(), + AcceptPIDFromInferior, + connect_url, + &lldb_error); + + + [applescript executeAndReturnError:nil]; + + thread_result_t accept_thread_result = NULL; + if (Host::ThreadJoin (accept_thread, &accept_thread_result, &lldb_error)) + { + if (accept_thread_result) + { + pid = (intptr_t)accept_thread_result; + + // Wait for process to be stopped the the entry point by watching + // for the process status to be set to SSTOP which indicates it it + // SIGSTOP'ed at the entry point + WaitForProcessToSIGSTOP (pid, 5); + } + } + [applescript release]; return pid; } + + +#define LLDB_HOST_USE_APPLESCRIPT + +lldb::pid_t +Host::LaunchInNewTerminal +( + const char **argv, + const char **envp, + const ArchSpec *arch_spec, + bool stop_at_entry, + bool disable_aslr +) +{ +#if defined (LLDB_HOST_USE_APPLESCRIPT) + return LaunchInNewTerminalWithAppleScript (argv, envp, arch_spec, stop_at_entry, disable_aslr); +#else + return LaunchInNewTerminalWithCommandFile (argv, envp, arch_spec, stop_at_entry, disable_aslr); #endif +} + bool Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no) diff --git a/lldb/tools/darwin-debug/darwin-debug.cpp b/lldb/tools/darwin-debug/darwin-debug.cpp index a38bfc249d4..de9b270a18f 100644 --- a/lldb/tools/darwin-debug/darwin-debug.cpp +++ b/lldb/tools/darwin-debug/darwin-debug.cpp @@ -253,6 +253,11 @@ int main (int argc, char *const *argv, char *const *envp, const char **apple) // We are done with the socket close (s); + system("clear"); + printf ("Launching '%s' for debug with %u arguments:\n", argv[0], argc); + for (int i=0; i<argc; ++i) + printf ("argv[%u] = '%s'\n", i, argv[i]); + // Now we posix spawn to exec this process into the inferior that we want // to debug. posix_spawn_for_debug (argv, |

