// Launch creates and begins debugging a new process. Uses a // custom fork/exec process in order to take advantage of // PT_SIGEXC on Darwin which will turn Unix signals into // Mach exceptions. func Launch(cmd []string) (*Process, error) { // check that the argument to Launch is an executable file if fi, staterr := os.Stat(cmd[0]); staterr == nil && (fi.Mode()&0111) == 0 { return nil, NotExecutableErr } argv0Go, err := filepath.Abs(cmd[0]) if err != nil { return nil, err } // Make sure the binary exists. if filepath.Base(cmd[0]) == cmd[0] { if _, err := exec.LookPath(cmd[0]); err != nil { return nil, err } } if _, err := os.Stat(argv0Go); err != nil { return nil, err } argv0 := C.CString(argv0Go) argvSlice := make([]*C.char, 0, len(cmd)+1) for _, arg := range cmd { argvSlice = append(argvSlice, C.CString(arg)) } // argv array must be null terminated. argvSlice = append(argvSlice, nil) dbp := New(0) var pid int dbp.execPtraceFunc(func() { ret := C.fork_exec(argv0, &argvSlice[0], C.int(len(argvSlice)), &dbp.os.task, &dbp.os.portSet, &dbp.os.exceptionPort, &dbp.os.notificationPort) pid = int(ret) }) if pid <= 0 { return nil, fmt.Errorf("could not fork/exec") } dbp.Pid = pid for i := range argvSlice { C.free(unsafe.Pointer(argvSlice[i])) } dbp, err = initializeDebugProcess(dbp, argv0Go, false) if err != nil { return nil, err } err = dbp.Continue() return dbp, err }
// Create and begin debugging a new process. Uses a // custom fork/exec process in order to take advantage of // PT_SIGEXC on Darwin which will turn Unix signals into // Mach exceptions. func Launch(cmd []string) (*Process, error) { argv0Go, err := filepath.Abs(cmd[0]) if err != nil { return nil, err } // Make sure the binary exists. if filepath.Base(cmd[0]) == cmd[0] { if _, err := exec.LookPath(cmd[0]); err != nil { return nil, err } } if _, err := os.Stat(argv0Go); err != nil { return nil, err } argv0 := C.CString(argv0Go) argvSlice := make([]*C.char, 0, len(cmd)) for _, arg := range cmd { argvSlice = append(argvSlice, C.CString(arg)) } var argv **C.char argv = &argvSlice[0] dbp := New(0) var pid int dbp.execPtraceFunc(func() { ret := C.fork_exec(argv0, argv, &dbp.os.task, &dbp.os.portSet, &dbp.os.exceptionPort, &dbp.os.notificationPort) pid = int(ret) }) if pid <= 0 { return nil, fmt.Errorf("could not fork/exec") } dbp.Pid = pid for i := range argvSlice { C.free(unsafe.Pointer(argvSlice[i])) } dbp, err = initializeDebugProcess(dbp, argv0Go, false) if err != nil { return nil, err } err = dbp.Continue() return dbp, err }