1
0
mirror of https://github.com/golang/go synced 2024-11-26 19:51:17 -07:00

misc/ios: support go run in go_darwin_arm_exec

The -lldb flag makes it easy to use go run and end up in a debugging
session on darwin/arm.

Change-Id: I556f93e950086a7dff4839f301b9c55f7579f87b
Reviewed-on: https://go-review.googlesource.com/8024
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
David Crawshaw 2015-03-06 09:45:24 -05:00
parent 93644c9118
commit 4345a9fc5d

View File

@ -5,6 +5,12 @@
// This program can be used as go_darwin_arm_exec by the Go tool. // This program can be used as go_darwin_arm_exec by the Go tool.
// It executes binaries on an iOS device using the XCode toolchain // It executes binaries on an iOS device using the XCode toolchain
// and the ios-deploy program: https://github.com/phonegap/ios-deploy // and the ios-deploy program: https://github.com/phonegap/ios-deploy
//
// This script supports an extra flag, -lldb, that pauses execution
// just before the main program begins and allows the user to control
// the remote lldb session. This flag is appended to the end of the
// script's arguments and is not passed through to the underlying
// binary.
package main package main
import ( import (
@ -13,6 +19,7 @@ import (
"flag" "flag"
"fmt" "fmt"
"go/build" "go/build"
"io"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
@ -139,6 +146,9 @@ func run(bin string, args []string) (err error) {
exec.Command("killall", "ios-deploy").Run() exec.Command("killall", "ios-deploy").Run()
var opts options
opts, args = parseArgs(args)
// ios-deploy invokes lldb to give us a shell session with the app. // ios-deploy invokes lldb to give us a shell session with the app.
cmd = exec.Command( cmd = exec.Command(
// lldb tries to be clever with terminals. // lldb tries to be clever with terminals.
@ -165,8 +175,14 @@ func run(bin string, args []string) (err error) {
return err return err
} }
w := new(bufWriter) w := new(bufWriter)
cmd.Stdout = w if opts.lldb {
cmd.Stderr = w // everything of interest is on stderr mw := io.MultiWriter(w, os.Stderr)
cmd.Stdout = mw
cmd.Stderr = mw
} else {
cmd.Stdout = w
cmd.Stderr = w // everything of interest is on stderr
}
cmd.Stdin = lldbr cmd.Stdin = lldbr
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
@ -177,9 +193,9 @@ func run(bin string, args []string) (err error) {
// of moving parts in an iOS test harness (notably lldb) that can // of moving parts in an iOS test harness (notably lldb) that can
// swallow useful stdio or cause its own ruckus. // swallow useful stdio or cause its own ruckus.
var timedout chan struct{} var timedout chan struct{}
if t := parseTimeout(args); t > 1*time.Second { if opts.timeout > 1*time.Second {
timedout = make(chan struct{}) timedout = make(chan struct{})
time.AfterFunc(t-1*time.Second, func() { time.AfterFunc(opts.timeout-1*time.Second, func() {
close(timedout) close(timedout)
}) })
} }
@ -232,6 +248,14 @@ func run(bin string, args []string) (err error) {
do(`process handle SIGSEGV --stop false --pass true --notify false`) // does not work do(`process handle SIGSEGV --stop false --pass true --notify false`) // does not work
do(`process handle SIGBUS --stop false --pass true --notify false`) // does not work do(`process handle SIGBUS --stop false --pass true --notify false`) // does not work
if opts.lldb {
_, err := io.Copy(lldb, os.Stdin)
if err != io.EOF {
return err
}
return nil
}
do(`breakpoint set -n getwd`) // in runtime/cgo/gcc_darwin_arm.go do(`breakpoint set -n getwd`) // in runtime/cgo/gcc_darwin_arm.go
fmt.Fprintln(lldb, `run`) fmt.Fprintln(lldb, `run`)
@ -257,11 +281,13 @@ func run(bin string, args []string) (err error) {
} }
// Move the current working directory into the faux gopath. // Move the current working directory into the faux gopath.
do(`breakpoint delete 1`) if pkgpath != "src" {
do(`expr char* $mem = (char*)malloc(512)`) do(`breakpoint delete 1`)
do(`expr $mem = (char*)getwd($mem, 512)`) do(`expr char* $mem = (char*)malloc(512)`)
do(`expr $mem = (char*)strcat($mem, "/` + pkgpath + `")`) do(`expr $mem = (char*)getwd($mem, 512)`)
do(`call (void)chdir($mem)`) do(`expr $mem = (char*)strcat($mem, "/` + pkgpath + `")`)
do(`call (void)chdir($mem)`)
}
// Watch for SIGSEGV. Ideally lldb would never break on SIGSEGV. // Watch for SIGSEGV. Ideally lldb would never break on SIGSEGV.
// http://golang.org/issue/10043 // http://golang.org/issue/10043
@ -408,20 +434,29 @@ func (w *bufWriter) isPass() bool {
return bytes.Contains(w.buf, []byte("\nPASS\n")) || bytes.Contains(w.buf, []byte("\nPASS\r")) return bytes.Contains(w.buf, []byte("\nPASS\n")) || bytes.Contains(w.buf, []byte("\nPASS\r"))
} }
func parseTimeout(testArgs []string) (timeout time.Duration) { type options struct {
var args []string timeout time.Duration
for _, arg := range testArgs { lldb bool
if strings.Contains(arg, "test.timeout") { }
args = append(args, arg)
func parseArgs(binArgs []string) (opts options, remainingArgs []string) {
var flagArgs []string
for _, arg := range binArgs {
if strings.Contains(arg, "-test.timeout") {
flagArgs = append(flagArgs, arg)
} }
if strings.Contains(arg, "-lldb") {
flagArgs = append(flagArgs, arg)
continue
}
remainingArgs = append(remainingArgs, arg)
} }
f := flag.NewFlagSet("", flag.ContinueOnError) f := flag.NewFlagSet("", flag.ContinueOnError)
f.DurationVar(&timeout, "test.timeout", 0, "") f.DurationVar(&opts.timeout, "test.timeout", 0, "")
f.Parse(args) f.BoolVar(&opts.lldb, "lldb", false, "")
if debug { f.Parse(flagArgs)
log.Printf("parseTimeout of %s, got %s", args, timeout) return opts, remainingArgs
}
return timeout
} }
func copyLocalDir(dst, src string) error { func copyLocalDir(dst, src string) error {