Upstreaming the apple internal changes that accumulated during the
previous release.  Most of the diffs are duplication in the xcode
project file caused by adding a "debugserver-mini" target.  Jim
Ingham added support for a new SPI needed to request app launches
on iOS.  Greg Clayton added code to indicate the platform of the
binary (macosx, ios, watchos, tvos) based on Mach-O load commands.
Jason Molenda added code so debugserver will identify when it is
running on a tvos/watchos device to lldb.

llvm-svn: 251091
diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp
index 53b42cd..03c85df 100644
--- a/lldb/tools/debugserver/source/DNB.cpp
+++ b/lldb/tools/debugserver/source/DNB.cpp
@@ -747,7 +747,7 @@
         if (attach_token != NULL)
         {
             nub_process_t pid;
-            pid = MachProcess::CheckForProcess(attach_token);
+            pid = MachProcess::CheckForProcess(attach_token, launch_flavor);
             if (pid != INVALID_NUB_PROCESS)
             {
                 waitfor_pid = pid;
@@ -825,7 +825,7 @@
     }
 
     bool success = waitfor_pid != INVALID_NUB_PROCESS;
-    MachProcess::CleanupAfterAttach (attach_token, success, prepare_error);
+    MachProcess::CleanupAfterAttach (attach_token, launch_flavor, success, prepare_error);
 
     return waitfor_pid;
 }
diff --git a/lldb/tools/debugserver/source/DNBDefs.h b/lldb/tools/debugserver/source/DNBDefs.h
index 1abcb61..e3757e9 100644
--- a/lldb/tools/debugserver/source/DNBDefs.h
+++ b/lldb/tools/debugserver/source/DNBDefs.h
@@ -96,9 +96,11 @@
     eLaunchFlavorSpringBoard = 3,
 #endif
 #ifdef WITH_BKS
-    eLaunchFlavorBKS = 4
+    eLaunchFlavorBKS = 4,
 #endif
-
+#ifdef WITH_FBS
+    eLaunchFlavorFBS = 5
+#endif
 } nub_launch_flavor_t;
 
 #define NUB_STATE_IS_RUNNING(s) ((s) == eStateAttaching ||\
diff --git a/lldb/tools/debugserver/source/DNBError.cpp b/lldb/tools/debugserver/source/DNBError.cpp
index b4f3990..c9d8ebd 100644
--- a/lldb/tools/debugserver/source/DNBError.cpp
+++ b/lldb/tools/debugserver/source/DNBError.cpp
@@ -54,7 +54,17 @@
                 // You have to call ObjC routines to get the error string from BackBoardServices.
                 // Not sure I want to make DNBError.cpp an .mm file.  For now just make sure you
                 // pre-populate the error string when you make the DNBError of type BackBoard.
-                m_str.assign("Should have set Backboard error when making the error string.");
+                m_str.assign("Should have set BackBoard error when making the error string.");
+            }
+            break;
+#endif
+#ifdef WITH_FBS
+        case FrontBoard:
+            {
+                // You have to call ObjC routines to get the error string from FrontBoardServices.
+                // Not sure I want to make DNBError.cpp an .mm file.  For now just make sure you
+                // pre-populate the error string when you make the DNBError of type FrontBoard.
+                m_str.assign("Should have set FrontBoard error when making the error string.");
             }
             break;
 #endif
diff --git a/lldb/tools/debugserver/source/DNBError.h b/lldb/tools/debugserver/source/DNBError.h
index 3f8fa2f..274ae0d 100644
--- a/lldb/tools/debugserver/source/DNBError.h
+++ b/lldb/tools/debugserver/source/DNBError.h
@@ -34,6 +34,9 @@
 #ifdef WITH_BKS
         , BackBoard = 4
 #endif
+#ifdef WITH_FBS
+        , FrontBoard = 5
+#endif
     } FlavorType;
 
     explicit DNBError(    ValueType err = 0,
diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.h b/lldb/tools/debugserver/source/MacOSX/MachProcess.h
index 0795a78..3be0b2d 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachProcess.h
+++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.h
@@ -14,6 +14,12 @@
 #ifndef __MachProcess_h__
 #define __MachProcess_h__
 
+#include <mach/mach.h>
+#include <sys/signal.h>
+#include <pthread.h>
+#include <vector>
+#include <CoreFoundation/CoreFoundation.h>
+
 #include "DNBDefs.h"
 #include "DNBBreakpoint.h"
 #include "DNBError.h"
@@ -29,11 +35,6 @@
 #include "ThreadInfo.h"
 #include "JSONGenerator.h"
 
-#include <mach/mach.h>
-#include <sys/signal.h>
-#include <pthread.h>
-#include <vector>
-
 class DNBThreadResumeActions;
 
 class MachProcess
@@ -78,19 +79,24 @@
                                                                DNBError& err);
     nub_addr_t              GetDYLDAllImageInfosAddress ();
     static const void *     PrepareForAttach (const char *path, nub_launch_flavor_t launch_flavor, bool waitfor, DNBError &err_str);
-    static void             CleanupAfterAttach (const void *attach_token, bool success, DNBError &err_str);
-    static nub_process_t    CheckForProcess (const void *attach_token);
+    static void             CleanupAfterAttach (const void *attach_token, nub_launch_flavor_t launch_flavor, bool success, DNBError &err_str);
+    static nub_process_t    CheckForProcess (const void *attach_token, nub_launch_flavor_t launch_flavor);
+#if defined(WITH_BKS) || defined(WITH_FBS)
+    pid_t                   BoardServiceLaunchForDebug (const char *app_bundle_path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, const char *event_data, DNBError &launch_err);
+    pid_t                   BoardServiceForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, const char *event_data, DNBError &launch_err);
+    bool                    BoardServiceSendEvent (const char *event, DNBError &error);
+#endif
     static bool             GetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch);
 #ifdef WITH_BKS
-    pid_t                   BKSLaunchForDebug (const char *app_bundle_path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, const char *event_data, DNBError &launch_err);
-    pid_t                   BKSForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, const char *event_data, DNBError &launch_err);
-    bool                    BKSSendEvent (const char *event, DNBError &error);
     static void             BKSCleanupAfterAttach (const void *attach_token, DNBError &err_str);
-#endif
+#endif // WITH_BKS
+#ifdef WITH_FBS
+    static void             FBSCleanupAfterAttach (const void *attach_token, DNBError &err_str);
+#endif  // WITH_FBS
 #ifdef WITH_SPRINGBOARD
     pid_t                   SBLaunchForDebug (const char *app_bundle_path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, DNBError &launch_err);
     static pid_t            SBForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], bool no_stdio, MachProcess* process, DNBError &launch_err);
-#endif
+#endif  // WITH_SPRINGBOARD
     nub_addr_t              LookupSymbol (const char *name, const char *shlib);
     void                    SetNameToAddressCallback (DNBCallbackNameToAddress callback, void *baton)
                             {
@@ -287,7 +293,8 @@
         eMachProcessFlagsNone = 0,
         eMachProcessFlagsAttached = (1 << 0),
         eMachProcessFlagsUsingSBS = (1 << 1),
-        eMachProcessFlagsUsingBKS = (1 << 2)
+        eMachProcessFlagsUsingBKS = (1 << 2),
+        eMachProcessFlagsUsingFBS = (1 << 3)
     };
     void                    Clear (bool detaching = false);
     void                    ReplyToAllExceptions ();
diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.mm b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm
index c4ba9e2..b9e0630 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachProcess.mm
+++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm
@@ -44,44 +44,6 @@
 #include "CFData.h"
 #include "CFString.h"
 
-#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS)
-// This returns a CFRetained pointer to the Bundle ID for app_bundle_path,
-// or NULL if there was some problem getting the bundle id.
-static CFStringRef
-CopyBundleIDForPath (const char *app_bundle_path, DNBError &err_str)
-{
-    CFBundle bundle(app_bundle_path);
-    CFStringRef bundleIDCFStr = bundle.GetIdentifier();
-    std::string bundleID;
-    if (CFString::UTF8(bundleIDCFStr, bundleID) == NULL)
-    {
-        struct stat app_bundle_stat;
-        char err_msg[PATH_MAX];
-        
-        if (::stat (app_bundle_path, &app_bundle_stat) < 0)
-        {
-            err_str.SetError(errno, DNBError::POSIX);
-            snprintf(err_msg, sizeof(err_msg), "%s: \"%s\"", err_str.AsString(), app_bundle_path);
-            err_str.SetErrorString(err_msg);
-            DNBLogThreadedIf(LOG_PROCESS, "%s() error: %s", __FUNCTION__, err_msg);
-        }
-        else
-        {
-            err_str.SetError(-1, DNBError::Generic);
-            snprintf(err_msg, sizeof(err_msg), "failed to extract CFBundleIdentifier from %s", app_bundle_path);
-            err_str.SetErrorString(err_msg);
-            DNBLogThreadedIf(LOG_PROCESS, "%s() error: failed to extract CFBundleIdentifier from '%s'", __FUNCTION__, app_bundle_path);
-        }
-        return NULL;
-    }
-    
-    DNBLogThreadedIf(LOG_PROCESS, "%s() extracted CFBundleIdentifier: %s", __FUNCTION__, bundleID.c_str());
-    CFRetain (bundleIDCFStr);
-    
-    return bundleIDCFStr;
-}
-#endif // #if defined 9WITH_SPRINGBOARD) || defined (WITH_BKS)
-
 #ifdef WITH_SPRINGBOARD
 
 #include <CoreFoundation/CoreFoundation.h>
@@ -97,6 +59,123 @@
 
 #endif // WITH_SPRINGBOARD
 
+#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS)
+// This returns a CFRetained pointer to the Bundle ID for app_bundle_path,
+// or NULL if there was some problem getting the bundle id.
+static CFStringRef CopyBundleIDForPath (const char *app_bundle_path, DNBError &err_str);
+#endif
+
+#if defined(WITH_BKS) || defined(WITH_FBS)
+#import <Foundation/Foundation.h>
+static const int OPEN_APPLICATION_TIMEOUT_ERROR = 111;
+typedef void (*SetErrorFunction) (NSInteger, DNBError &);
+typedef bool (*CallOpenApplicationFunction) (NSString *bundleIDNSStr, NSDictionary *options, DNBError &error, pid_t *return_pid);
+// This function runs the BKSSystemService (or FBSSystemService) method openApplication:options:clientPort:withResult,
+// messaging the app passed in bundleIDNSStr.
+// The function should be run inside of an NSAutoReleasePool.
+//
+// It will use the "options" dictionary passed in, and fill the error passed in if there is an error.
+// If return_pid is not NULL, we'll fetch the pid that was made for the bundleID.
+// If bundleIDNSStr is NULL, then the system application will be messaged.
+
+template <typename OpenFlavor, typename ErrorFlavor, ErrorFlavor no_error_enum_value, SetErrorFunction error_function>
+static bool
+CallBoardSystemServiceOpenApplication (NSString *bundleIDNSStr, NSDictionary *options, DNBError &error, pid_t *return_pid)
+{
+    // Now make our systemService:
+    OpenFlavor *system_service = [[OpenFlavor alloc] init];
+    
+    if (bundleIDNSStr == nil)
+    {
+        bundleIDNSStr = [system_service systemApplicationBundleIdentifier];
+        if (bundleIDNSStr == nil)
+        {
+            // Okay, no system app...
+            error.SetErrorString("No system application to message.");
+            return false;
+        }
+    }
+        
+    mach_port_t client_port = [system_service createClientPort];
+    __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
+    __block  ErrorFlavor open_app_error = no_error_enum_value;
+    bool wants_pid = (return_pid != NULL);
+    __block pid_t pid_in_block;
+    
+    const char *cstr = [bundleIDNSStr UTF8String];
+    if (!cstr)
+        cstr = "<Unknown Bundle ID>";
+    
+    DNBLog ("About to launch process for bundle ID: %s", cstr);
+    [system_service openApplication: bundleIDNSStr
+                    options: options
+                    clientPort: client_port
+                    withResult: ^(NSError *bks_error)
+        {
+                        // The system service will cleanup the client port we created for us.
+                        if (bks_error)
+                            open_app_error = (ErrorFlavor)[bks_error code];
+                                        
+                        if (open_app_error == no_error_enum_value)
+                        {
+                            if (wants_pid)
+                            {
+                                pid_in_block = [system_service pidForApplication: bundleIDNSStr];
+                                DNBLog("In completion handler, got pid for bundle id, pid: %d.", pid_in_block);
+                                DNBLogThreadedIf(LOG_PROCESS, "In completion handler, got pid for bundle id, pid: %d.", pid_in_block);
+                            }
+                            else
+                                DNBLogThreadedIf (LOG_PROCESS, "In completion handler: success.");
+        }
+        else
+        {
+                            const char *error_str = [(NSString *)[bks_error localizedDescription] UTF8String];
+                            DNBLogThreadedIf(LOG_PROCESS, "In completion handler for send event, got error \"%s\"(%ld).",
+                                             error_str ? error_str : "<unknown error>",
+                                             open_app_error);
+                            // REMOVE ME
+                            DNBLogError ("In completion handler for send event, got error \"%s\"(%ld).",
+                                             error_str ? error_str : "<unknown error>",
+                                             open_app_error);
+        }
+ 
+                        [system_service release];
+                        dispatch_semaphore_signal(semaphore);
+    }
+    
+    ];
+    
+    const uint32_t timeout_secs = 9;
+
+    dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC);
+
+    long success = dispatch_semaphore_wait(semaphore, timeout) == 0;
+
+    dispatch_release(semaphore);
+    
+    if (!success)
+{
+        DNBLogError("timed out trying to send openApplication to %s.", cstr);
+        error.SetError (OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic);
+        error.SetErrorString ("timed out trying to launch app");
+    }
+    else if (open_app_error != no_error_enum_value)
+    {
+        error_function (open_app_error, error);
+        DNBLogError("unable to launch the application with CFBundleIdentifier '%s' bks_error = %u", cstr, open_app_error);
+        success = false;
+    }
+    else if (wants_pid)
+    {
+        *return_pid = pid_in_block;
+        DNBLogThreadedIf (LOG_PROCESS, "Out of completion handler, pid from block %d and passing out: %d", pid_in_block, *return_pid);
+}
+
+
+    return success;
+}
+#endif
+
 #ifdef WITH_BKS
 #import <Foundation/Foundation.h>
 extern "C"
@@ -115,10 +194,10 @@
 }
 
 static void
-SetBKSError (BKSOpenApplicationErrorCode error_code, DNBError &error)
+SetBKSError (NSInteger error_code, DNBError &error)
 {
     error.SetError (error_code, DNBError::BackBoard);
-    NSString *err_nsstr = ::BKSOpenApplicationErrorCodeToString(error_code);
+    NSString *err_nsstr = ::BKSOpenApplicationErrorCodeToString((BKSOpenApplicationErrorCode) error_code);
     const char *err_str = NULL;
     if (err_nsstr == NULL)
         err_str = "unknown BKS error";
@@ -131,8 +210,164 @@
     error.SetErrorString(err_str);
 }
 
-static const int BKS_OPEN_APPLICATION_TIMEOUT_ERROR = 111;
+static bool
+BKSAddEventDataToOptions (NSMutableDictionary *options, const char *event_data, DNBError &option_error)
+{
+    if (strcmp (event_data, "BackgroundContentFetching") == 0)
+    {
+        DNBLog("Setting ActivateForEvent key in options dictionary.");
+        NSDictionary *event_details = [NSDictionary dictionary];
+        NSDictionary *event_dictionary = [NSDictionary dictionaryWithObject:event_details forKey:BKSActivateForEventOptionTypeBackgroundContentFetching];
+        [options setObject: event_dictionary forKey: BKSOpenApplicationOptionKeyActivateForEvent];
+        return true;
+    }
+    else
+    {
+        DNBLogError ("Unrecognized event type: %s.  Ignoring.", event_data);
+        option_error.SetErrorString("Unrecognized event data.");
+        return false;
+    }
+    
+}
+
+static NSMutableDictionary *
+BKSCreateOptionsDictionary(const char *app_bundle_path, NSMutableArray *launch_argv, NSMutableDictionary *launch_envp, NSString *stdio_path, bool disable_aslr, const char *event_data)
+{
+    NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
+    if (launch_argv != nil)
+        [debug_options setObject: launch_argv forKey: BKSDebugOptionKeyArguments];
+    if (launch_envp != nil)
+        [debug_options setObject: launch_envp forKey: BKSDebugOptionKeyEnvironment];
+
+    [debug_options setObject: stdio_path forKey: BKSDebugOptionKeyStandardOutPath];
+    [debug_options setObject: stdio_path forKey: BKSDebugOptionKeyStandardErrorPath];
+    [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyWaitForDebugger];
+    if (disable_aslr)
+        [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyDisableASLR];
+    
+    // That will go in the overall dictionary:
+    
+    NSMutableDictionary *options = [NSMutableDictionary dictionary];
+    [options setObject: debug_options forKey: BKSOpenApplicationOptionKeyDebuggingOptions];
+    // And there are some other options at the top level in this dictionary:
+    [options setObject: [NSNumber numberWithBool: YES] forKey: BKSOpenApplicationOptionKeyUnlockDevice];
+
+    DNBError error;
+    BKSAddEventDataToOptions (options, event_data, error);
+
+    return options;
+}
+
+static CallOpenApplicationFunction BKSCallOpenApplicationFunction = CallBoardSystemServiceOpenApplication<BKSSystemService, BKSOpenApplicationErrorCode, BKSOpenApplicationErrorCodeNone, SetBKSError>;
 #endif // WITH_BKS
+
+#ifdef WITH_FBS
+#import <Foundation/Foundation.h>
+extern "C"
+{
+#import <FrontBoardServices/FrontBoardServices.h>
+#import <FrontBoardServices/FBSSystemService_LaunchServices.h>
+#import <FrontBoardServices/FBSOpenApplicationConstants_Private.h>
+#import <MobileCoreServices/MobileCoreServices.h>
+#import <MobileCoreServices/LSResourceProxy.h>
+}
+
+#ifdef WITH_BKS
+static bool
+IsFBSProcess (nub_process_t pid)
+{
+    BKSApplicationStateMonitor *state_monitor = [[BKSApplicationStateMonitor alloc] init];
+    BKSApplicationState app_state = [state_monitor mostElevatedApplicationStateForPID: pid];
+    return app_state != BKSApplicationStateUnknown;
+}
+#else
+static bool
+IsFBSProcess (nub_process_t pid)
+{
+    // FIXME: What is the FBS equivalent of BKSApplicationStateMonitor
+    return true;
+}
+#endif
+
+static void
+SetFBSError (NSInteger error_code, DNBError &error)
+{
+    error.SetError ((DNBError::ValueType) error_code, DNBError::FrontBoard);
+    NSString *err_nsstr = ::FBSOpenApplicationErrorCodeToString((FBSOpenApplicationErrorCode) error_code);
+    const char *err_str = NULL;
+    if (err_nsstr == NULL)
+        err_str = "unknown FBS error";
+    else
+    {
+        err_str = [err_nsstr UTF8String];
+        if (err_str == NULL)
+            err_str = "unknown FBS error";
+    }
+    error.SetErrorString(err_str);
+}
+
+static bool
+FBSAddEventDataToOptions (NSMutableDictionary *options, const char *event_data, DNBError &option_error)
+{
+    if (strcmp (event_data, "BackgroundContentFetching") == 0)
+    {
+        DNBLog("Setting ActivateForEvent key in options dictionary.");
+        NSDictionary *event_details = [NSDictionary dictionary];
+        NSDictionary *event_dictionary = [NSDictionary dictionaryWithObject:event_details forKey:FBSActivateForEventOptionTypeBackgroundContentFetching];
+        [options setObject: event_dictionary forKey: FBSOpenApplicationOptionKeyActivateForEvent];
+        return true;
+    }
+    else
+    {
+        DNBLogError ("Unrecognized event type: %s.  Ignoring.", event_data);
+        option_error.SetErrorString("Unrecognized event data.");
+        return false;
+    }
+    
+}
+
+static NSMutableDictionary *
+FBSCreateOptionsDictionary(const char *app_bundle_path, NSMutableArray *launch_argv, NSDictionary *launch_envp, NSString *stdio_path, bool disable_aslr, const char *event_data)
+{
+    NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
+
+    if (launch_argv != nil)
+        [debug_options setObject: launch_argv forKey: FBSDebugOptionKeyArguments];
+    if (launch_envp != nil)
+        [debug_options setObject: launch_envp forKey: FBSDebugOptionKeyEnvironment];
+
+    [debug_options setObject: stdio_path forKey: FBSDebugOptionKeyStandardOutPath];
+    [debug_options setObject: stdio_path forKey: FBSDebugOptionKeyStandardErrorPath];
+    [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyWaitForDebugger];
+    if (disable_aslr)
+        [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyDisableASLR];
+    
+    // That will go in the overall dictionary:
+    
+    NSMutableDictionary *options = [NSMutableDictionary dictionary];
+    [options setObject: debug_options forKey: FBSOpenApplicationOptionKeyDebuggingOptions];
+    // And there are some other options at the top level in this dictionary:
+    [options setObject: [NSNumber numberWithBool: YES] forKey: FBSOpenApplicationOptionKeyUnlockDevice];
+
+    // We have to get the "sequence ID & UUID" for this app bundle path and send them to FBS:
+
+    NSURL *app_bundle_url = [NSURL fileURLWithPath: [NSString stringWithUTF8String: app_bundle_path] isDirectory: YES];
+    LSApplicationProxy *app_proxy = [LSApplicationProxy applicationProxyForBundleURL: app_bundle_url];
+    if (app_proxy)
+    {
+        DNBLog("Sending AppProxy info: sequence no: %lu, GUID: %s.", app_proxy.sequenceNumber, [app_proxy.cacheGUID.UUIDString UTF8String]);
+        [options setObject: [NSNumber numberWithUnsignedInteger: app_proxy.sequenceNumber] forKey: FBSOpenApplicationOptionKeyLSSequenceNumber];
+        [options setObject: app_proxy.cacheGUID.UUIDString forKey: FBSOpenApplicationOptionKeyLSCacheGUID];
+    }
+
+    DNBError error;
+    FBSAddEventDataToOptions (options, event_data, error);
+
+    return options;
+}
+static CallOpenApplicationFunction FBSCallOpenApplicationFunction = CallBoardSystemServiceOpenApplication<FBSSystemService, FBSOpenApplicationErrorCode, FBSOpenApplicationErrorCodeNone, SetFBSError>;
+#endif // WITH_FBS
+
 #if 0
 #define DEBUG_LOG(fmt, ...) printf(fmt, ## __VA_ARGS__)
 #else
@@ -863,8 +1098,9 @@
     DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SendEvent (event = %s) to pid: %d", event, m_pid);
     if (m_pid == INVALID_NUB_PROCESS)
         return false;
-#if WITH_BKS
-    return BKSSendEvent (event, send_err);
+    // FIXME: Shouldn't we use the launch flavor we were started with?
+#if defined(WITH_FBS) || defined(WITH_BKS)
+    return BoardServiceSendEvent (event, send_err);
 #endif
     return true;
 }
@@ -1970,9 +2206,22 @@
         SetState(eStateAttaching);
         m_pid = pid;
         // Let ourselves know we are going to be using SBS or BKS if the correct flag bit is set...
-#if defined (WITH_BKS)
-        if (IsBKSProcess (pid))
+#if defined (WITH_FBS) || defined (WITH_BKS)
+        bool found_app_flavor = false;
+#endif
+        
+#if defined (WITH_FBS)
+        if (!found_app_flavor && IsFBSProcess (pid))
+        {
+            found_app_flavor = true;
+            m_flags |= eMachProcessFlagsUsingFBS;
+        }
+#elif defined (WITH_BKS)
+        if (!found_app_flavor && IsBKSProcess (pid))
+        {
+            found_app_flavor = true;
             m_flags |= eMachProcessFlagsUsingBKS;
+        }
 #elif defined (WITH_SPRINGBOARD)
         if (IsSBProcess(pid))
             m_flags |= eMachProcessFlagsUsingSBS;
@@ -2058,7 +2307,7 @@
 const void *
 MachProcess::PrepareForAttach (const char *path, nub_launch_flavor_t launch_flavor, bool waitfor, DNBError &attach_err)
 {
-#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS)
+#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS)
     // Tell SpringBoard to halt the next launch of this application on startup.
 
     if (!waitfor)
@@ -2074,7 +2323,12 @@
         return NULL;
     }
 
-#if defined (WITH_BKS)
+#if defined (WITH_FBS)
+    if (launch_flavor == eLaunchFlavorDefault)
+        launch_flavor = eLaunchFlavorFBS;
+    if (launch_flavor != eLaunchFlavorFBS)
+        return NULL;
+#elif defined (WITH_BKS)
     if (launch_flavor == eLaunchFlavorDefault)
         launch_flavor = eLaunchFlavorBKS;
     if (launch_flavor != eLaunchFlavorBKS)
@@ -2101,6 +2355,76 @@
         return NULL;
     }
 
+#if defined (WITH_FBS)
+    if (launch_flavor == eLaunchFlavorFBS)
+    {
+        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+        NSString *stdio_path = nil;
+        NSFileManager *file_manager = [NSFileManager defaultManager];
+        const char *null_path = "/dev/null";
+        stdio_path = [file_manager stringWithFileSystemRepresentation: null_path length: strlen(null_path)];
+
+        NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
+        NSMutableDictionary *options       = [NSMutableDictionary dictionary];
+
+        DNBLogThreadedIf(LOG_PROCESS, "Calling BKSSystemService openApplication: @\"%s\",options include stdio path: \"%s\", "
+                                      "BKSDebugOptionKeyDebugOnNextLaunch & BKSDebugOptionKeyWaitForDebugger )",
+                                      bundleIDStr.c_str(),
+                                      null_path);
+        
+        [debug_options setObject: stdio_path forKey: FBSDebugOptionKeyStandardOutPath];
+        [debug_options setObject: stdio_path forKey: FBSDebugOptionKeyStandardErrorPath];
+        [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyWaitForDebugger];
+        [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyDebugOnNextLaunch];
+        
+        [options setObject: debug_options forKey: FBSOpenApplicationOptionKeyDebuggingOptions];
+
+        FBSSystemService *system_service = [[FBSSystemService alloc] init];
+                
+        mach_port_t client_port = [system_service createClientPort];
+        __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
+        __block FBSOpenApplicationErrorCode attach_error_code = FBSOpenApplicationErrorCodeNone;
+        
+        NSString *bundleIDNSStr = (NSString *) bundleIDCFStr;
+        
+        [system_service openApplication: bundleIDNSStr
+                       options: options
+                       clientPort: client_port
+                       withResult: ^(NSError *error)
+                       {
+                            // The system service will cleanup the client port we created for us.
+                            if (error)
+                                attach_error_code = (FBSOpenApplicationErrorCode)[error code];
+                                                                       
+                            [system_service release];
+                            dispatch_semaphore_signal(semaphore);
+                        }
+        ];
+        
+        const uint32_t timeout_secs = 9;
+        
+        dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC);
+        
+        long success = dispatch_semaphore_wait(semaphore, timeout) == 0;
+        
+        if (!success)
+        {
+            DNBLogError("timed out trying to launch %s.", bundleIDStr.c_str());
+            attach_err.SetErrorString("debugserver timed out waiting for openApplication to complete.");
+            attach_err.SetError (OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic);
+        }
+        else if (attach_error_code != FBSOpenApplicationErrorCodeNone)
+        {
+            SetFBSError (attach_error_code, attach_err);
+            DNBLogError("unable to launch the application with CFBundleIdentifier '%s' bks_error = %ld",
+                        bundleIDStr.c_str(),
+                        (NSInteger) attach_error_code);
+        }
+        dispatch_release(semaphore);
+        [pool drain];
+    }
+#endif
 #if defined (WITH_BKS)
     if (launch_flavor == eLaunchFlavorBKS)
     {
@@ -2158,19 +2482,21 @@
         {
             DNBLogError("timed out trying to launch %s.", bundleIDStr.c_str());
             attach_err.SetErrorString("debugserver timed out waiting for openApplication to complete.");
-            attach_err.SetError (BKS_OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic);
+            attach_err.SetError (OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic);
         }
         else if (attach_error_code != BKSOpenApplicationErrorCodeNone)
         {
             SetBKSError (attach_error_code, attach_err);
-            DNBLogError("unable to launch the application with CFBundleIdentifier '%s' bks_error = %u",
+            DNBLogError("unable to launch the application with CFBundleIdentifier '%s' bks_error = %ld",
                         bundleIDStr.c_str(),
                         attach_error_code);
         }
         dispatch_release(semaphore);
         [pool drain];
     }
-#elif defined (WITH_SPRINGBOARD)
+#endif
+
+#if defined (WITH_SPRINGBOARD)
     if (launch_flavor == eLaunchFlavorSpringBoard)
     {
         SBSApplicationLaunchError sbs_error = 0;
@@ -2203,7 +2529,7 @@
 
     DNBLogThreadedIf(LOG_PROCESS, "Successfully set DebugOnNextLaunch.");
     return bundleIDCFStr;
-# else  // defined (WITH_SPRINGBOARD) || defined (WITH_BKS)
+# else  // !(defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS))
   return NULL;
 #endif
 }
@@ -2213,12 +2539,28 @@
 // will be returned.
 
 nub_process_t
-MachProcess::CheckForProcess (const void *attach_token)
+MachProcess::CheckForProcess (const void *attach_token, nub_launch_flavor_t launch_flavor)
 {
     if (attach_token == NULL)
         return INVALID_NUB_PROCESS;
 
+#if defined (WITH_FBS)
+    if (launch_flavor == eLaunchFlavorFBS)
+    {
+        NSString *bundleIDNSStr = (NSString *) attach_token;
+        FBSSystemService *systemService = [[FBSSystemService alloc] init];
+        pid_t pid = [systemService pidForApplication: bundleIDNSStr];
+        [systemService release];
+        if (pid == 0)
+            return INVALID_NUB_PROCESS;
+        else
+            return pid;
+    }
+#endif
+
 #if defined (WITH_BKS)
+    if (launch_flavor == eLaunchFlavorBKS)
+    {
     NSString *bundleIDNSStr = (NSString *) attach_token;
     BKSSystemService *systemService = [[BKSSystemService alloc] init];
     pid_t pid = [systemService pidForApplication: bundleIDNSStr];
@@ -2227,7 +2569,12 @@
         return INVALID_NUB_PROCESS;
     else
         return pid;
-#elif defined (WITH_SPRINGBOARD)
+    }
+#endif
+
+#if defined (WITH_SPRINGBOARD)
+    if (launch_flavor == eLaunchFlavorSpringBoard)
+    {
     CFStringRef bundleIDCFStr = (CFStringRef) attach_token;
     Boolean got_it;
     nub_process_t attach_pid;
@@ -2236,9 +2583,9 @@
         return attach_pid;
     else
         return INVALID_NUB_PROCESS;
-#else
-    return INVALID_NUB_PROCESS;
+    }
 #endif
+    return INVALID_NUB_PROCESS;
 }
 
 // Call this to clean up after you have either attached or given up on the attach.
@@ -2247,22 +2594,39 @@
 // this method.
 
 void
-MachProcess::CleanupAfterAttach (const void *attach_token, bool success, DNBError &err_str)
+MachProcess::CleanupAfterAttach (const void *attach_token, nub_launch_flavor_t launch_flavor, bool success, DNBError &err_str)
 {
     if (attach_token == NULL)
         return;
 
+#if defined (WITH_FBS)
+    if (launch_flavor == eLaunchFlavorFBS)
+    {
+        if (!success)
+        {
+            FBSCleanupAfterAttach (attach_token, err_str);
+        }
+        CFRelease((CFStringRef) attach_token);
+    }
+#endif
+
 #if defined (WITH_BKS)
 
+    if (launch_flavor == eLaunchFlavorBKS)
+    {
     if (!success)
     {
         BKSCleanupAfterAttach (attach_token, err_str);
     }
     CFRelease((CFStringRef) attach_token);
+    }
+#endif
     
-#elif defined (WITH_SPRINGBOARD)
+#if defined (WITH_SPRINGBOARD)
     // Tell SpringBoard to cancel the debug on next launch of this application
     // if we failed to attach
+    if (launch_flavor == eMachProcessFlagsUsingSpringBoard)
+    {
     if (!success)
     {
         SBSApplicationLaunchError sbs_error = 0;
@@ -2284,6 +2648,7 @@
     }
 
     CFRelease((CFStringRef) attach_token);
+    }
 #endif
 }
 
@@ -2317,6 +2682,22 @@
     case eLaunchFlavorForkExec:
         m_pid = MachProcess::ForkChildForPTraceDebugging (path, argv, envp, this, launch_err);
         break;
+#ifdef WITH_FBS
+    case eLaunchFlavorFBS:
+        {
+            const char *app_ext = strstr(path, ".app");
+            if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/'))
+            {
+                std::string app_bundle_path(path, app_ext + strlen(".app"));
+                m_flags |= eMachProcessFlagsUsingFBS;
+                if (BoardServiceLaunchForDebug (app_bundle_path.c_str(), argv, envp, no_stdio, disable_aslr, event_data, launch_err) != 0)
+                    return m_pid; // A successful SBLaunchForDebug() returns and assigns a non-zero m_pid.
+                else
+                    break; // We tried a FBS launch, but didn't succeed lets get out
+            }
+        }
+        break;
+#endif
 #ifdef WITH_BKS
     case eLaunchFlavorBKS:
         {
@@ -2324,7 +2705,8 @@
             if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/'))
             {
                 std::string app_bundle_path(path, app_ext + strlen(".app"));
-                if (BKSLaunchForDebug (app_bundle_path.c_str(), argv, envp, no_stdio, disable_aslr, event_data, launch_err) != 0)
+                m_flags |= eMachProcessFlagsUsingBKS;
+                if (BoardServiceLaunchForDebug (app_bundle_path.c_str(), argv, envp, no_stdio, disable_aslr, event_data, launch_err) != 0)
                     return m_pid; // A successful SBLaunchForDebug() returns and assigns a non-zero m_pid.
                 else
                     break; // We tried a BKS launch, but didn't succeed lets get out
@@ -2719,6 +3101,43 @@
     return pid;
 }
 
+#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS)
+// This returns a CFRetained pointer to the Bundle ID for app_bundle_path,
+// or NULL if there was some problem getting the bundle id.
+static CFStringRef
+CopyBundleIDForPath (const char *app_bundle_path, DNBError &err_str)
+{
+    CFBundle bundle(app_bundle_path);
+    CFStringRef bundleIDCFStr = bundle.GetIdentifier();
+    std::string bundleID;
+    if (CFString::UTF8(bundleIDCFStr, bundleID) == NULL)
+    {
+        struct stat app_bundle_stat;
+        char err_msg[PATH_MAX];
+
+        if (::stat (app_bundle_path, &app_bundle_stat) < 0)
+        {
+            err_str.SetError(errno, DNBError::POSIX);
+            snprintf(err_msg, sizeof(err_msg), "%s: \"%s\"", err_str.AsString(), app_bundle_path);
+            err_str.SetErrorString(err_msg);
+            DNBLogThreadedIf(LOG_PROCESS, "%s() error: %s", __FUNCTION__, err_msg);
+        }
+        else
+        {
+            err_str.SetError(-1, DNBError::Generic);
+            snprintf(err_msg, sizeof(err_msg), "failed to extract CFBundleIdentifier from %s", app_bundle_path);
+            err_str.SetErrorString(err_msg);
+            DNBLogThreadedIf(LOG_PROCESS, "%s() error: failed to extract CFBundleIdentifier from '%s'", __FUNCTION__, app_bundle_path);
+        }
+        return NULL;
+    }
+
+    DNBLogThreadedIf(LOG_PROCESS, "%s() extracted CFBundleIdentifier: %s", __FUNCTION__, bundleID.c_str());
+    CFRetain (bundleIDCFStr);
+
+    return bundleIDCFStr;
+}
+#endif // #if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS)
 #ifdef WITH_SPRINGBOARD
 
 pid_t
@@ -2929,178 +3348,19 @@
 
 #endif // #ifdef WITH_SPRINGBOARD
 
-#ifdef WITH_BKS
-
-
-// This function runs the BKSSystemService method openApplication:options:clientPort:withResult,
-// messaging the app passed in bundleIDNSStr.
-// The function should be run inside of an NSAutoReleasePool.
-//
-// It will use the "options" dictionary passed in, and fill the error passed in if there is an error.
-// If return_pid is not NULL, we'll fetch the pid that was made for the bundleID.
-// If bundleIDNSStr is NULL, then the system application will be messaged.
-
-static bool
-CallBKSSystemServiceOpenApplication (NSString *bundleIDNSStr, NSDictionary *options, DNBError &error, pid_t *return_pid)
-{
-    // Now make our systemService:
-    BKSSystemService *system_service = [[BKSSystemService alloc] init];
-    
-    if (bundleIDNSStr == nil)
-    {
-        bundleIDNSStr = [system_service systemApplicationBundleIdentifier];
-        if (bundleIDNSStr == nil)
-        {
-            // Okay, no system app...
-            error.SetErrorString("No system application to message.");
-            return false;
-        }
-    }
-    
-    mach_port_t client_port = [system_service createClientPort];
-    __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
-    __block BKSOpenApplicationErrorCode open_app_error = BKSOpenApplicationErrorCodeNone;
-    bool wants_pid = (return_pid != NULL);
-    __block pid_t pid_in_block;
-    
-    const char *cstr = [bundleIDNSStr UTF8String];
-    if (!cstr)
-        cstr = "<Unknown Bundle ID>";
-    
-    DNBLog ("About to launch process for bundle ID: %s", cstr);
-    [system_service openApplication: bundleIDNSStr
-                    options: options
-                    clientPort: client_port
-                    withResult: ^(NSError *bks_error)
-                    {
-                        // The system service will cleanup the client port we created for us.
-                        if (bks_error)
-                            open_app_error = (BKSOpenApplicationErrorCode)[bks_error code];
-                                        
-                        if (open_app_error == BKSOpenApplicationErrorCodeNone)
-                        {
-                            if (wants_pid)
-                            {
-                                pid_in_block = [system_service pidForApplication: bundleIDNSStr];
-                                DNBLog("In completion handler, got pid for bundle id, pid: %d.", pid_in_block);
-                                DNBLogThreadedIf(LOG_PROCESS, "In completion handler, got pid for bundle id, pid: %d.", pid_in_block);
-                            }
-                            else
-                                DNBLogThreadedIf (LOG_PROCESS, "In completion handler: success.");
-                        }
-                        else
-                        {
-                            const char *error_str = [[bks_error localizedDescription] UTF8String];
-                            DNBLogThreadedIf(LOG_PROCESS, "In completion handler for send event, got error \"%s\"(%d).",
-                                             error_str ? error_str : "<unknown error>",
-                                             open_app_error);
-                            // REMOVE ME
-                            DNBLogError ("In completion handler for send event, got error \"%s\"(%d).",
-                                             error_str ? error_str : "<unknown error>",
-                                             open_app_error);
-                        }
- 
-                        [system_service release];
-                        dispatch_semaphore_signal(semaphore);
-                    }
-
-    ];
-    
-    const uint32_t timeout_secs = 9;
-    
-    dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC);
-    
-    long success = dispatch_semaphore_wait(semaphore, timeout) == 0;
-    
-    dispatch_release(semaphore);
-    
-    if (!success)
-    {
-        DNBLogError("timed out trying to send openApplication to %s.", cstr);
-        error.SetError (BKS_OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic);
-        error.SetErrorString ("timed out trying to launch app");
-    }
-    else if (open_app_error != BKSOpenApplicationErrorCodeNone)
-    {
-        SetBKSError (open_app_error, error);
-        DNBLogError("unable to launch the application with CFBundleIdentifier '%s' bks_error = %u", cstr, open_app_error);
-        success = false;
-    }
-    else if (wants_pid)
-    {
-        *return_pid = pid_in_block;
-        DNBLogThreadedIf (LOG_PROCESS, "Out of completion handler, pid from block %d and passing out: %d", pid_in_block, *return_pid);
-    }
     
 
-    return success;
-}
-
-void
-MachProcess::BKSCleanupAfterAttach (const void *attach_token, DNBError &err_str)
-{
-    bool success;
-    
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-    
-    // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use toll-free bridging here:
-    NSString *bundleIDNSStr = (NSString *) attach_token;
-
-    // Okay, now let's assemble all these goodies into the BackBoardServices options mega-dictionary:
-    
-    // First we have the debug sub-dictionary:
-    NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
-    [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyCancelDebugOnNextLaunch];
-    
-    // That will go in the overall dictionary:
-    
-    NSMutableDictionary *options = [NSMutableDictionary dictionary];
-    [options setObject: debug_options forKey: BKSOpenApplicationOptionKeyDebuggingOptions];
-
-    success = CallBKSSystemServiceOpenApplication(bundleIDNSStr, options, err_str, NULL);
-    
-    if (!success)
-    {
-        DNBLogError ("error trying to cancel debug on next launch for %s: %s", [bundleIDNSStr UTF8String], err_str.AsString());
-    }
-
-    [pool drain];
-}
-
-bool
-AddEventDataToOptions (NSMutableDictionary *options, const char *event_data, DNBError &option_error)
-{
-    if (strcmp (event_data, "BackgroundContentFetching") == 0)
-    {
-        DNBLog("Setting ActivateForEvent key in options dictionary.");
-        NSDictionary *event_details = [NSDictionary dictionary];
-        NSDictionary *event_dictionary = [NSDictionary dictionaryWithObject:event_details forKey:BKSActivateForEventOptionTypeBackgroundContentFetching];
-        [options setObject: event_dictionary forKey: BKSOpenApplicationOptionKeyActivateForEvent];
-        return true;
-    }
-    else
-    {
-        DNBLogError ("Unrecognized event type: %s.  Ignoring.", event_data);
-        option_error.SetErrorString("Unrecognized event data.");
-        return false;
-    }
-    
-}
-
+#if defined (WITH_BKS) || defined (WITH_FBS)
 pid_t
-MachProcess::BKSLaunchForDebug (const char *path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, const char *event_data, DNBError &launch_err)
+MachProcess::BoardServiceLaunchForDebug (const char *path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, const char *event_data, DNBError &launch_err)
 {
-    // Clear out and clean up from any current state
-    Clear();
-
     DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path);
 
     // Fork a child process for debugging
     SetState(eStateLaunching);
-    m_pid = BKSForkChildForPTraceDebugging(path, argv, envp, no_stdio, disable_aslr, event_data, launch_err);
+    m_pid = BoardServiceForkChildForPTraceDebugging(path, argv, envp, no_stdio, disable_aslr, event_data, launch_err);
     if (m_pid != 0)
     {
-        m_flags |= eMachProcessFlagsUsingBKS;
         m_path = path;
         size_t i;
         char const *arg;
@@ -3136,7 +3396,7 @@
 }
 
 pid_t
-MachProcess::BKSForkChildForPTraceDebugging (const char *app_bundle_path,
+MachProcess::BoardServiceForkChildForPTraceDebugging (const char *app_bundle_path,
                                              char const *argv[],
                                              char const *envp[],
                                              bool no_stdio,
@@ -3242,40 +3502,24 @@
 
     // Okay, now let's assemble all these goodies into the BackBoardServices options mega-dictionary:
     
-    // First we have the debug sub-dictionary:
-    NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
-    if (launch_argv != nil)
-        [debug_options setObject: launch_argv forKey: BKSDebugOptionKeyArguments];
-    if (launch_envp != nil)
-        [debug_options setObject: launch_envp forKey: BKSDebugOptionKeyEnvironment];
-
-    [debug_options setObject: stdio_path forKey: BKSDebugOptionKeyStandardOutPath];
-    [debug_options setObject: stdio_path forKey: BKSDebugOptionKeyStandardErrorPath];
-    [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyWaitForDebugger];
-    if (disable_aslr)
-        [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyDisableASLR];
-    
-    // That will go in the overall dictionary:
-    
-    NSMutableDictionary *options = [NSMutableDictionary dictionary];
-    [options setObject: debug_options forKey: BKSOpenApplicationOptionKeyDebuggingOptions];
-
-    // For now we only support one kind of event: the "fetch" event, which is indicated by the fact that its data
-    // is an empty dictionary.
-    if (event_data != NULL && *event_data != '\0')
-    {
-        if (!AddEventDataToOptions(options, event_data, launch_err))
-        {
-            [pool drain];
-            return INVALID_NUB_PROCESS;
-        }
-    }
-    
-    // And there are some other options at the top level in this dictionary:
-    [options setObject: [NSNumber numberWithBool: YES] forKey: BKSOpenApplicationOptionKeyUnlockDevice];
-
+    NSMutableDictionary *options = nullptr;
     pid_t return_pid = INVALID_NUB_PROCESS;
-    bool success = CallBKSSystemServiceOpenApplication(bundleIDNSStr, options, launch_err, &return_pid);
+    bool success = false;
+
+#ifdef WITH_BKS
+    if (m_flags & eMachProcessFlagsUsingBKS)
+        {
+        options = BKSCreateOptionsDictionary(app_bundle_path, launch_argv, launch_envp, stdio_path, disable_aslr, event_data);
+        success = BKSCallOpenApplicationFunction (bundleIDNSStr, options, launch_err, &return_pid);
+        }
+#endif
+#ifdef WITH_FBS
+    if (m_flags & eMachProcessFlagsUsingFBS)
+    {
+        options = FBSCreateOptionsDictionary(app_bundle_path, launch_argv, launch_envp, stdio_path, disable_aslr, event_data);
+        success = FBSCallOpenApplicationFunction (bundleIDNSStr, options, launch_err, &return_pid);
+    }
+#endif
     
     if (success)
     {
@@ -3290,7 +3534,7 @@
 }
 
 bool
-MachProcess::BKSSendEvent (const char *event_data, DNBError &send_err)
+MachProcess::BoardServiceSendEvent (const char *event_data, DNBError &send_err)
 {
     bool return_value = true;
     
@@ -3306,7 +3550,18 @@
     if (strcmp (event_data, "BackgroundApplication") == 0)
     {
         // This is an event I cooked up.  What you actually do is foreground the system app, so:
-        return_value = CallBKSSystemServiceOpenApplication(nil, nil, send_err, NULL);
+#ifdef WITH_BKS
+        if (m_flags & eMachProcessFlagsUsingBKS)
+        {
+            return_value = BKSCallOpenApplicationFunction(nil, nil, send_err, NULL);
+        }
+#endif
+#ifdef WITH_FBS
+        if (m_flags & eMachProcessFlagsUsingFBS)
+        {
+            return_value = FBSCallOpenApplicationFunction(nil, nil, send_err, NULL);
+        }
+#endif
         if (!return_value)
         {
             DNBLogError ("Failed to background application, error: %s.", send_err.AsString());
@@ -3326,14 +3581,31 @@
         
         NSMutableDictionary *options = [NSMutableDictionary dictionary];
 
-        if (!AddEventDataToOptions(options, event_data, send_err))
+#ifdef WITH_BKS
+        if (m_flags & eMachProcessFlagsUsingBKS)
+        {
+            if (!BKSAddEventDataToOptions(options, event_data, send_err))
         {
             [pool drain];
             return false;
         }
+            return_value = BKSCallOpenApplicationFunction (bundleIDNSStr, options, send_err, NULL);
+            DNBLogThreadedIf (LOG_PROCESS, "Called BKSCallOpenApplicationFunction to send event.");
 
-
-        return_value = CallBKSSystemServiceOpenApplication(bundleIDNSStr, options, send_err, NULL);
+        }
+#endif
+#ifdef WITH_FBS
+        if (m_flags & eMachProcessFlagsUsingFBS)
+        {
+            if (!FBSAddEventDataToOptions(options, event_data, send_err))
+            {
+                [pool drain];
+                return false;
+            }
+            return_value = FBSCallOpenApplicationFunction (bundleIDNSStr, options, send_err, NULL);
+            DNBLogThreadedIf (LOG_PROCESS, "Called FBSCallOpenApplicationFunction to send event.");
+        }
+#endif
         
         if (!return_value)
         {
@@ -3344,4 +3616,70 @@
     [pool drain];
     return return_value;
 }
+#endif // defined(WITH_BKS) || defined (WITH_FBS)
+
+#ifdef WITH_BKS
+void
+MachProcess::BKSCleanupAfterAttach (const void *attach_token, DNBError &err_str)
+{
+    bool success;
+    
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    
+    // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use toll-free bridging here:
+    NSString *bundleIDNSStr = (NSString *) attach_token;
+
+    // Okay, now let's assemble all these goodies into the BackBoardServices options mega-dictionary:
+    
+    // First we have the debug sub-dictionary:
+    NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
+    [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyCancelDebugOnNextLaunch];
+    
+    // That will go in the overall dictionary:
+    
+    NSMutableDictionary *options = [NSMutableDictionary dictionary];
+    [options setObject: debug_options forKey: BKSOpenApplicationOptionKeyDebuggingOptions];
+
+    success = BKSCallOpenApplicationFunction (bundleIDNSStr, options, err_str, NULL);
+    
+    if (!success)
+    {
+        DNBLogError ("error trying to cancel debug on next launch for %s: %s", [bundleIDNSStr UTF8String], err_str.AsString());
+    }
+
+    [pool drain];
+}
 #endif // WITH_BKS
+
+#ifdef WITH_FBS
+void
+MachProcess::FBSCleanupAfterAttach (const void *attach_token, DNBError &err_str)
+{
+    bool success;
+    
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    
+    // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use toll-free bridging here:
+    NSString *bundleIDNSStr = (NSString *) attach_token;
+
+    // Okay, now let's assemble all these goodies into the BackBoardServices options mega-dictionary:
+    
+    // First we have the debug sub-dictionary:
+    NSMutableDictionary *debug_options = [NSMutableDictionary dictionary];
+    [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyCancelDebugOnNextLaunch];
+    
+    // That will go in the overall dictionary:
+    
+    NSMutableDictionary *options = [NSMutableDictionary dictionary];
+    [options setObject: debug_options forKey: FBSOpenApplicationOptionKeyDebuggingOptions];
+
+    success = FBSCallOpenApplicationFunction (bundleIDNSStr, options, err_str, NULL);
+
+    if (!success)
+    {
+        DNBLogError ("error trying to cancel debug on next launch for %s: %s", [bundleIDNSStr UTF8String], err_str.AsString());
+    }
+
+    [pool drain];
+}
+#endif // WITH_FBS
diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp
index 1f751de..2241fa0 100644
--- a/lldb/tools/debugserver/source/RNBRemote.cpp
+++ b/lldb/tools/debugserver/source/RNBRemote.cpp
@@ -17,6 +17,7 @@
 #include <unistd.h>
 #include <signal.h>
 #include <mach/exception_types.h>
+#include <mach-o/loader.h>
 #include <sys/stat.h>
 #include <sys/sysctl.h>
 
@@ -4608,7 +4609,14 @@
     // this for now.
     if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64)
     {
+#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1
+        strm << "ostype:tvos;";
+#elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
+        strm << "ostype:watchos;";
+#else
         strm << "ostype:ios;";
+#endif
+
         // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
         strm << "watchpoint_exceptions_received:before;";
     }
@@ -4655,6 +4663,11 @@
         strm << "ptrsize:8;";
     else
         strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
+
+#if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
+    strm << "default_packet_timeout:10;";
+#endif
+
     return SendPacket (strm.str());
 }
 
@@ -5514,6 +5527,138 @@
     return SendPacket ("OK");
 }
 
+static bool
+MachHeaderIsMainExecutable (nub_process_t pid, uint32_t addr_size, nub_addr_t mach_header_addr, mach_header &mh)
+{
+    DNBLogThreadedIf (LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = %u, mach_header_addr = 0x%16.16llx)", pid, addr_size, mach_header_addr);
+    const nub_size_t bytes_read = DNBProcessMemoryRead(pid, mach_header_addr, sizeof(mh), &mh);
+    if (bytes_read == sizeof(mh))
+    {
+        DNBLogThreadedIf (LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = %u, mach_header_addr = 0x%16.16llx): mh = {\n  magic = 0x%8.8x\n  cpu = 0x%8.8x\n  sub = 0x%8.8x\n  filetype = %u\n  ncmds = %u\n  sizeofcmds = 0x%8.8x\n  flags = 0x%8.8x }", pid, addr_size, mach_header_addr, mh.magic, mh.cputype, mh.cpusubtype, mh.filetype, mh.ncmds, mh.sizeofcmds, mh.flags);
+        if ((addr_size == 4 && mh.magic == MH_MAGIC) ||
+            (addr_size == 8 && mh.magic == MH_MAGIC_64))
+        {
+            if (mh.filetype == MH_EXECUTE)
+            {
+                DNBLogThreadedIf (LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = %u, mach_header_addr = 0x%16.16llx) -> this is the executable!!!", pid, addr_size, mach_header_addr);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+static nub_addr_t
+GetMachHeaderForMainExecutable (const nub_process_t pid, const uint32_t addr_size, mach_header &mh)
+{
+    struct AllImageInfos
+    {
+        uint32_t version;
+        uint32_t dylib_info_count;
+        uint64_t dylib_info_addr;
+    };
+
+    uint64_t mach_header_addr = 0;
+
+    const nub_addr_t shlib_addr = DNBProcessGetSharedLibraryInfoAddress (pid);
+    uint8_t bytes[256];
+    nub_size_t bytes_read = 0;
+    DNBDataRef data (bytes, sizeof(bytes), false);
+    DNBDataRef::offset_t offset = 0;
+    data.SetPointerSize(addr_size);
+
+    //----------------------------------------------------------------------
+    // When we are sitting at __dyld_start, the kernel has placed the
+    // address of the mach header of the main executable on the stack. If we
+    // read the SP and dereference a pointer, we might find the mach header
+    // for the executable. We also just make sure there is only 1 thread
+    // since if we are at __dyld_start we shouldn't have multiple threads.
+    //----------------------------------------------------------------------
+    if (DNBProcessGetNumThreads(pid) == 1)
+    {
+        nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, 0);
+        if (tid != INVALID_NUB_THREAD)
+        {
+            DNBRegisterValue sp_value;
+            if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_SP, &sp_value))
+            {
+                uint64_t sp = addr_size == 8 ? sp_value.value.uint64 : sp_value.value.uint32;
+                bytes_read = DNBProcessMemoryRead(pid, sp, addr_size, bytes);
+                if (bytes_read == addr_size)
+                {
+                    offset = 0;
+                    mach_header_addr = data.GetPointer(&offset);
+                    if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
+                        return mach_header_addr;
+                }
+            }
+        }
+    }
+
+    //----------------------------------------------------------------------
+    // Check the dyld_all_image_info structure for a list of mach header
+    // since it is a very easy thing to check
+    //----------------------------------------------------------------------
+    if (shlib_addr != INVALID_NUB_ADDRESS)
+    {
+        bytes_read = DNBProcessMemoryRead(pid, shlib_addr, sizeof(AllImageInfos), bytes);
+        if (bytes_read > 0)
+        {
+            AllImageInfos aii;
+            offset = 0;
+            aii.version = data.Get32(&offset);
+            aii.dylib_info_count = data.Get32(&offset);
+            if (aii.dylib_info_count > 0)
+            {
+                aii.dylib_info_addr = data.GetPointer(&offset);
+                if (aii.dylib_info_addr != 0)
+                {
+                    const size_t image_info_byte_size = 3 * addr_size;
+                    for (uint32_t i=0; i<aii.dylib_info_count; ++i)
+                    {
+                        bytes_read = DNBProcessMemoryRead(pid, aii.dylib_info_addr + i * image_info_byte_size, image_info_byte_size, bytes);
+                        if (bytes_read != image_info_byte_size)
+                            break;
+                        offset = 0;
+                        mach_header_addr = data.GetPointer(&offset);
+                        if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
+                            return mach_header_addr;
+                    }
+                }
+            }
+        }
+    }
+
+    //----------------------------------------------------------------------
+    // We failed to find the executable's mach header from the all image
+    // infos and by dereferencing the stack pointer. Now we fall back to
+    // enumerating the memory regions and looking for regions that are
+    // executable.
+    //----------------------------------------------------------------------
+    DNBRegionInfo region_info;
+    mach_header_addr = 0;
+    while (DNBProcessMemoryRegionInfo(pid, mach_header_addr, &region_info))
+    {
+        if (region_info.size == 0)
+            break;
+
+        if (region_info.permissions & eMemoryPermissionsExecutable)
+        {
+            DNBLogThreadedIf (LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx) permissions = %c%c%c: checking region for executable mach header", region_info.addr, region_info.addr + region_info.size, (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-', (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-', (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
+            if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
+                return mach_header_addr;
+        }
+        else
+        {
+            DNBLogThreadedIf (LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx): permissions = %c%c%c: skipping region", region_info.addr, region_info.addr + region_info.size, (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-', (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-', (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
+        }
+        // Set the address to the next mapped region
+        mach_header_addr = region_info.addr + region_info.size;
+    }
+    bzero (&mh, sizeof(mh));
+    return INVALID_NUB_ADDRESS;
+}
+
 rnb_err_t
 RNBRemote::HandlePacket_qSymbol (const char *command)
 {
@@ -5593,7 +5738,7 @@
 
     pid = m_ctx.ProcessID();
 
-    rep << "pid:" << std::hex << pid << ";";
+    rep << "pid:" << std::hex << pid << ';';
 
     int procpid_mib[4];
     procpid_mib[0] = CTL_KERN;
@@ -5607,12 +5752,12 @@
     {
         if (proc_kinfo_size > 0)
         {
-            rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ";";
-            rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid << ";";
-            rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid << ";";
-            rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid << ";";
+            rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';';
+            rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid << ';';
+            rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid << ';';
+            rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid << ';';
             if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
-                rep << "effective-gid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ";";
+                rep << "effective-gid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';';
         }
     }
     
@@ -5623,9 +5768,14 @@
         cputype = best_guess_cpu_type();
     }
 
+    uint32_t addr_size = 0;
     if (cputype != 0)
     {
         rep << "cputype:" << std::hex << cputype << ";";
+        if (cputype & CPU_ARCH_ABI64)
+            addr_size = 8;
+        else
+            addr_size = 4;
     }
 
     bool host_cpu_is_64bit = false;
@@ -5660,11 +5810,82 @@
         rep << "cpusubtype:" << std::hex << cpusubtype << ';';
     }
 
+    bool os_handled = false;
+    if (addr_size > 0)
+    {
+        rep << "ptrsize:" << std::dec << addr_size << ';';
+
+#if (defined (__x86_64__) || defined (__i386__))
+        // Try and get the OS type by looking at the load commands in the main
+        // executable and looking for a LC_VERSION_MIN load command. This is the
+        // most reliable way to determine the "ostype" value when on desktop.
+
+        mach_header mh;
+        nub_addr_t exe_mach_header_addr = GetMachHeaderForMainExecutable (pid, addr_size, mh);
+        if (exe_mach_header_addr != INVALID_NUB_ADDRESS)
+        {
+            uint64_t load_command_addr = exe_mach_header_addr + ((addr_size == 8) ? sizeof(mach_header_64) : sizeof(mach_header));
+            load_command lc;
+            for (uint32_t i=0; i<mh.ncmds && !os_handled; ++i)
+            {
+                const nub_size_t bytes_read = DNBProcessMemoryRead (pid, load_command_addr, sizeof(lc), &lc);
+                uint32_t raw_cmd = lc.cmd & ~LC_REQ_DYLD;
+                if (bytes_read != sizeof(lc))
+                    break;
+                switch (raw_cmd)
+                {
+                case LC_VERSION_MIN_IPHONEOS:
+                    os_handled = true;
+                    rep << "ostype:ios;";
+                    DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_IPHONEOS -> 'ostype:ios;'");
+                    break;
+
+                case LC_VERSION_MIN_MACOSX:
+                    os_handled = true;
+                    rep << "ostype:macosx;";
+                    DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_MACOSX -> 'ostype:macosx;'");
+                    break;
+
+#if defined (DT_VARIANT_PONDEROSA) || TARGET_OS_TV == 1
+                case LC_VERSION_MIN_TVOS:
+                    os_handled = true;
+                    rep << "ostype:tvos;";
+                    DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_TVOS -> 'ostype:tvos;'");
+                    break;
+#endif
+
+                case LC_VERSION_MIN_WATCHOS:
+                    os_handled = true;
+                    rep << "ostype:watchos;";
+                    DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_WATCHOS -> 'ostype:watchos;'");
+                    break;
+
+                default:
+                    break;
+                }
+                load_command_addr = load_command_addr + lc.cmdsize;
+            }
+        }
+#endif
+    }
+
+    // If we weren't able to find the OS in a LC_VERSION_MIN load command, try
+    // to set it correctly by using the cpu type and other tricks
+    if (!os_handled)
+    {
     // The OS in the triple should be "ios" or "macosx" which doesn't match our
     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
     // this for now.
     if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64)
+        {
+#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1
+            rep << "ostype:tvos;";
+#elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
+            rep << "ostype:watchos;";
+#else
         rep << "ostype:ios;";
+#endif
+        }
     else
     {
         bool is_ios_simulator = false;
@@ -5716,10 +5937,21 @@
             }
         }
         if (is_ios_simulator)
+            {
+#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1
+                rep << "ostype:tvos;";
+#elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
+                rep << "ostype:watchos;";
+#else
             rep << "ostype:ios;";
+#endif
+            }
         else
+            {
             rep << "ostype:macosx;";
     }
+        }
+    }
 
     rep << "vendor:apple;";
 
@@ -5731,6 +5963,8 @@
     rep << "endian:pdp;";
 #endif
 
+    if (addr_size == 0)
+    {
 #if (defined (__x86_64__) || defined (__i386__)) && defined (x86_THREAD_STATE)
     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort (pid);
     kern_return_t kr;
@@ -5764,6 +5998,7 @@
             rep << "ptrsize:4;";
     }
 #endif
+    }
 
     return SendPacket (rep.str());
 }
diff --git a/lldb/tools/debugserver/source/com.apple.debugserver.applist.internal.plist b/lldb/tools/debugserver/source/com.apple.debugserver.applist.internal.plist
index 6fb9aff..e9a74bd 100644
--- a/lldb/tools/debugserver/source/com.apple.debugserver.applist.internal.plist
+++ b/lldb/tools/debugserver/source/com.apple.debugserver.applist.internal.plist
@@ -10,5 +10,7 @@
 		<string>--lockdown</string>
 		<string>--applist</string>
 	</array>
+    <key>AllowByProxy</key>
+    <true/>
 </dict>
 </plist>
diff --git a/lldb/tools/debugserver/source/com.apple.debugserver.applist.plist b/lldb/tools/debugserver/source/com.apple.debugserver.applist.plist
index bd4037c..002e90d 100644
--- a/lldb/tools/debugserver/source/com.apple.debugserver.applist.plist
+++ b/lldb/tools/debugserver/source/com.apple.debugserver.applist.plist
@@ -11,7 +11,9 @@
 		<string>/Developer/usr/bin/debugserver</string>
 		<string>--lockdown</string>
         <string>--applist</string>
-        <string>--launch=backboard</string>
+        <string>--launch=frontboard</string>
 	</array>
+    <key>AllowByProxy</key>
+    <true/>
 </dict>
 </plist>
diff --git a/lldb/tools/debugserver/source/com.apple.debugserver.internal.plist b/lldb/tools/debugserver/source/com.apple.debugserver.internal.plist
index 923dc58..b9f57f7 100644
--- a/lldb/tools/debugserver/source/com.apple.debugserver.internal.plist
+++ b/lldb/tools/debugserver/source/com.apple.debugserver.internal.plist
@@ -9,5 +9,7 @@
 		<string>/Developer/usr/bin/debugserver</string>
 		<string>--lockdown</string>
 	</array>
+    <key>AllowByProxy</key>
+    <true/>
 </dict>
 </plist>
diff --git a/lldb/tools/debugserver/source/com.apple.debugserver.plist b/lldb/tools/debugserver/source/com.apple.debugserver.plist
index f61a2ac..c07466e 100644
--- a/lldb/tools/debugserver/source/com.apple.debugserver.plist
+++ b/lldb/tools/debugserver/source/com.apple.debugserver.plist
@@ -10,7 +10,9 @@
 	<array>
 		<string>/Developer/usr/bin/debugserver</string>
 		<string>--lockdown</string>
-        <string>--launch=backboard</string>
+        <string>--launch=frontboard</string>
 	</array>
+    <key>AllowByProxy</key>
+    <true/>
 </dict>
 </plist>
diff --git a/lldb/tools/debugserver/source/com.apple.debugserver.posix.plist b/lldb/tools/debugserver/source/com.apple.debugserver.posix.plist
index 9e4ca77..4083f8a 100644
--- a/lldb/tools/debugserver/source/com.apple.debugserver.posix.plist
+++ b/lldb/tools/debugserver/source/com.apple.debugserver.posix.plist
@@ -12,5 +12,7 @@
 		<string>--lockdown</string>
 		<string>--launch=posix</string>
 	</array>
+    <key>AllowByProxy</key>
+    <true/>
 </dict>
 </plist>
diff --git a/lldb/tools/debugserver/source/debugserver-entitlements.plist b/lldb/tools/debugserver/source/debugserver-entitlements.plist
index 84e0ca4..1b1fa6c 100644
--- a/lldb/tools/debugserver/source/debugserver-entitlements.plist
+++ b/lldb/tools/debugserver/source/debugserver-entitlements.plist
@@ -8,6 +8,10 @@
 	<true/>
 	<key>com.apple.backboardd.debugapplications</key>
 	<true/>
+    <key>com.apple.frontboard.launchapplications</key>
+    <true/>
+    <key>com.apple.frontboard.debugapplications</key>
+    <true/>
 	<key>run-unsigned-code</key>
 	<true/>
 	<key>seatbelt-profiles</key>
diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp
index afd5b00..33d39af 100644
--- a/lldb/tools/debugserver/source/debugserver.cpp
+++ b/lldb/tools/debugserver/source/debugserver.cpp
@@ -202,7 +202,13 @@
         // Our default launch method is posix spawn
         launch_flavor = eLaunchFlavorPosixSpawn;
 
-#if defined WITH_BKS
+#if defined WITH_FBS
+        // Check if we have an app bundle, if so launch using BackBoard Services.
+        if (strstr(inferior_argv[0], ".app"))
+        {
+            launch_flavor = eLaunchFlavorFBS;
+        }
+#elif defined WITH_BKS
         // Check if we have an app bundle, if so launch using BackBoard Services.
         if (strstr(inferior_argv[0], ".app"))
         {
@@ -1094,6 +1100,10 @@
                     else if (strcasestr(optarg, "backboard") == optarg)
                         g_launch_flavor = eLaunchFlavorBKS;
 #endif
+#ifdef WITH_FBS
+                    else if (strcasestr(optarg, "frontboard") == optarg)
+                        g_launch_flavor = eLaunchFlavorFBS;
+#endif
 
                     else
                     {
@@ -1108,6 +1118,9 @@
 #ifdef WITH_BKS
                         RNBLogSTDERR ("  backboard  Launch the executable through BackBoard Services.\n");
 #endif
+#ifdef WITH_FBS
+                        RNBLogSTDERR ("  frontboard  Launch the executable through FrontBoard Services.\n");
+#endif
                         exit (5);
                     }
                 }
@@ -1484,7 +1497,13 @@
                         // Our default launch method is posix spawn
                         launch_flavor = eLaunchFlavorPosixSpawn;
 
-#if defined WITH_BKS
+#if defined WITH_FBS
+                        // Check if we have an app bundle, if so launch using SpringBoard.
+                        if (waitfor_pid_name.find (".app") != std::string::npos)
+                        {
+                            launch_flavor = eLaunchFlavorFBS;
+                        }
+#elif defined WITH_BKS
                         // Check if we have an app bundle, if so launch using SpringBoard.
                         if (waitfor_pid_name.find (".app") != std::string::npos)
                         {