mirror of
https://github.com/blacktop/ipsw.git
synced 2026-05-08 12:22:26 +00:00
170 lines
2.8 KiB
Go
170 lines
2.8 KiB
Go
package debugserver
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type EventOutput struct {
|
|
output []byte
|
|
}
|
|
|
|
type EventThread struct{}
|
|
|
|
type Process struct {
|
|
c *Client
|
|
stdoutR *io.PipeReader
|
|
stdoutW *io.PipeWriter
|
|
interupt chan struct{}
|
|
name string
|
|
args []string
|
|
env []string
|
|
}
|
|
|
|
func makeArgs(args []string) string {
|
|
var ret []string
|
|
for i, arg := range args {
|
|
encoded := hex.EncodeToString([]byte(arg))
|
|
ret = append(ret,
|
|
strconv.Itoa(len(encoded)),
|
|
strconv.Itoa(i),
|
|
encoded)
|
|
}
|
|
return "A" + strings.Join(ret, ",")
|
|
}
|
|
|
|
func NewProcess(udid string, args, env []string) (*Process, error) {
|
|
client, err := NewClient(udid)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
stdoutR, stdoutW := io.Pipe()
|
|
p := &Process{
|
|
c: client,
|
|
interupt: make(chan struct{}, 1),
|
|
stdoutR: stdoutR,
|
|
stdoutW: stdoutW,
|
|
args: args,
|
|
env: env,
|
|
}
|
|
|
|
return p, nil
|
|
}
|
|
|
|
func (p *Process) Args() []string {
|
|
return p.args
|
|
}
|
|
|
|
func (p *Process) Stdout() io.Reader {
|
|
return p.stdoutR
|
|
}
|
|
|
|
func (p *Process) continueLoop() error {
|
|
for {
|
|
pck, err := p.c.Recv()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if pck == "" {
|
|
continue
|
|
}
|
|
switch pck[0] {
|
|
case 'O':
|
|
data, err := hex.DecodeString(pck[1:])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
p.stdoutW.Write(data)
|
|
case 'T':
|
|
p.interupt <- struct{}{}
|
|
return nil
|
|
default:
|
|
return fmt.Errorf("unkown packet: %s", pck)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *Process) requests(commands ...string) error {
|
|
for _, cmd := range commands {
|
|
if _, err := p.c.Request(cmd); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *Process) Start() error {
|
|
seq := []string{
|
|
makeArgs(p.Args()),
|
|
}
|
|
for _, e := range p.env {
|
|
seq = append(seq, "QEnvironmentHexEncoded:"+hex.EncodeToString([]byte(e)))
|
|
}
|
|
seq = append(seq, "qLaunchSuccess")
|
|
|
|
if err := p.start(seq...); err != nil {
|
|
return err
|
|
}
|
|
return p.Continue()
|
|
}
|
|
|
|
func (p *Process) Continue() error {
|
|
go p.continueLoop()
|
|
return p.c.Send("c")
|
|
}
|
|
|
|
func (p *Process) Interrupt() error {
|
|
if _, err := p.c.Conn().Write([]byte{'\003'}); err != nil {
|
|
return err
|
|
}
|
|
<-p.interupt
|
|
return nil
|
|
}
|
|
|
|
func (p *Process) Kill() error {
|
|
if err := p.Interrupt(); err != nil {
|
|
return err
|
|
}
|
|
if _, err := p.c.Request("k"); err != nil {
|
|
return err
|
|
}
|
|
return p.stdoutW.Close()
|
|
}
|
|
|
|
func (p *Process) bootstrap() error {
|
|
return p.requests(
|
|
"QStartNoAckMode",
|
|
"QEnableErrorStrings",
|
|
"QSetDetachOnError:1",
|
|
"QSetDisableASLR:1",
|
|
"qProcessInfo",
|
|
)
|
|
}
|
|
|
|
func (p *Process) start(commands ...string) error {
|
|
if err := p.bootstrap(); err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, cmd := range commands {
|
|
if _, err := p.c.Request(cmd); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *Process) WaitByName(name string) error {
|
|
if err := p.start(
|
|
"vAttachWait;" + hex.EncodeToString([]byte(name)),
|
|
); err != nil {
|
|
return err
|
|
}
|
|
return p.Continue()
|
|
}
|