debug: Implement passing of command-line arguments to the debugged program.

Changes the name of client.Run to client.New to better describe what it
does; previously users had to call two functions named Run to load and
start a program.

Removes the unimplemented function SetArguments, and instead arguments
are specified in the call to Run.

Change-Id: I12c3178b431efc01841242a88feee2f69b44d330
Reviewed-on: https://go-review.googlesource.com/10564
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/ogle/demo/ogler/ogler_test.go b/ogle/demo/ogler/ogler_test.go
index f3640b6..fef5aff 100644
--- a/ogle/demo/ogler/ogler_test.go
+++ b/ogle/demo/ogler/ogler_test.go
@@ -148,12 +148,12 @@
 		prog program.Program
 		err  error
 	)
-	prog, err = client.Run("localhost", traceeBinary)
+	prog, err = client.New("localhost", traceeBinary)
 	if err != nil {
-		log.Fatalf("Run: %v", err)
+		log.Fatalf("New: %v", err)
 	}
 
-	_, err = prog.Run()
+	_, err = prog.Run("some", "arguments")
 	if err != nil {
 		log.Fatalf("Run: %v", err)
 	}
diff --git a/ogle/demo/tracee/main.go b/ogle/demo/tracee/main.go
index a9cf90d..9b44649 100644
--- a/ogle/demo/tracee/main.go
+++ b/ogle/demo/tracee/main.go
@@ -8,6 +8,8 @@
 
 import (
 	"fmt"
+	"log"
+	"os"
 	"time"
 	"unsafe"
 )
@@ -100,6 +102,11 @@
 }
 
 func main() {
+	args := os.Args[1:]
+	expected := []string{"some", "arguments"}
+	if len(args) != 2 || args[0] != expected[0] || args[1] != expected[1] {
+		log.Fatalf("Got command-line args %v, expected %v", args, expected)
+	}
 	for ; ; time.Sleep(2 * time.Second) {
 		bar()
 	}
diff --git a/ogle/program/client/client.go b/ogle/program/client/client.go
index 94e4a9d..1eade3a 100644
--- a/ogle/program/client/client.go
+++ b/ogle/program/client/client.go
@@ -25,19 +25,9 @@
 var OgleproxyCmd = "ogleproxy"
 
 // New connects to the specified host using SSH, starts an ogle proxy
-// there, and creates a new program from the specified file with the specified
-// arguments, which include the program name the first argument.
-// The program is created but stops before executing the first instruction,
-// ready for debugging.
-func New(host string, textFile string, args ...string) (*Program, error) {
-	panic("unimplemented")
-}
-
-// Run connects to the specified host using SSH, starts an ogle proxy
-// there, and runs a new program from the specified file with the specified
-// arguments, which include the program name the first argument.
-// It is similar to New except that the program is allowed to run.
-func Run(host string, textFile string, args ...string) (*Program, error) {
+// there, and creates a new program from the specified file.
+// The program can then be started by the Run method.
+func New(host string, textFile string) (*Program, error) {
 	// TODO: add args.
 	cmdStrs := []string{"/usr/bin/ssh", host, OgleproxyCmd, "-text", textFile}
 	if host == "localhost" {
@@ -162,12 +152,8 @@
 	return f, nil
 }
 
-func (p *Program) SetArguments(args ...string) {
-	panic("unimplemented")
-}
-
-func (p *Program) Run() (program.Status, error) {
-	req := proxyrpc.RunRequest{}
+func (p *Program) Run(args ...string) (program.Status, error) {
+	req := proxyrpc.RunRequest{args}
 	var resp proxyrpc.RunResponse
 	err := p.client.Call("Server.Run", &req, &resp)
 	if err != nil {
diff --git a/ogle/program/program.go b/ogle/program/program.go
index fc86f46..34b3961 100644
--- a/ogle/program/program.go
+++ b/ogle/program/program.go
@@ -23,20 +23,14 @@
 	// file in the new process.
 	Open(name string, mode string) (File, error)
 
-	// SetArguments sets the command-line arguments for
-	// the next running of the target binary, excluding the
-	// target's binary name. That is, while debugging the
-	// echo command, to prepare a run of "echo hi" call
-	//	SetArguments("hi")
-	SetArguments(args ...string)
-
 	// Run abandons the current running process, if any,
 	// and execs a new instance of the target binary file
 	// (which may have changed underfoot).
 	// Breakpoints and open files are re-established.
 	// The call hangs until the program stops executing,
 	// at which point it returns the program status.
-	Run() (Status, error)
+	// args contains the command-line arguments for the process.
+	Run(args ...string) (Status, error)
 
 	// Stop stops execution of the current process but
 	// does not kill it.
diff --git a/ogle/program/proxyrpc/proxyrpc.go b/ogle/program/proxyrpc/proxyrpc.go
index 18d551f..04b2240 100644
--- a/ogle/program/proxyrpc/proxyrpc.go
+++ b/ogle/program/proxyrpc/proxyrpc.go
@@ -63,6 +63,7 @@
 }
 
 type RunRequest struct {
+	Args []string
 }
 
 type RunResponse struct {
diff --git a/ogle/program/server/server.go b/ogle/program/server/server.go
index 3444a75..1a3ca3e 100644
--- a/ogle/program/server/server.go
+++ b/ogle/program/server/server.go
@@ -267,7 +267,8 @@
 		s.stoppedRegs = syscall.PtraceRegs{}
 		s.topOfStackAddrs = nil
 	}
-	p, err := s.startProcess(s.executable, nil, &os.ProcAttr{
+	argv := append([]string{s.executable}, req.Args...)
+	p, err := s.startProcess(s.executable, argv, &os.ProcAttr{
 		Files: []*os.File{
 			nil,       // TODO: be able to feed the target's stdin.
 			os.Stderr, // TODO: be able to capture the target's stdout.