github.com/undoio/delve@v1.9.0/pkg/proc/gdbserial/gdbserver_conn.go (about) 1 package gdbserial 2 3 import ( 4 "bufio" 5 "bytes" 6 "debug/macho" 7 "encoding/json" 8 "encoding/xml" 9 "errors" 10 "fmt" 11 "io" 12 "net" 13 "os" 14 "strconv" 15 "strings" 16 "syscall" 17 "time" 18 19 "github.com/sirupsen/logrus" 20 "github.com/undoio/delve/pkg/logflags" 21 "github.com/undoio/delve/pkg/proc" 22 ) 23 24 type gdbConn struct { 25 conn net.Conn 26 rdr *bufio.Reader 27 28 inbuf []byte 29 outbuf bytes.Buffer 30 31 running bool 32 33 direction proc.Direction // direction of execution 34 35 packetSize int // maximum packet size supported by stub 36 regsInfo []gdbRegisterInfo // list of registers 37 38 workaroundReg *gdbRegisterInfo // used to work-around a register setting bug in debugserver, see use in gdbserver.go 39 40 pid int // cache process id 41 42 ack bool // when ack is true acknowledgment packets are enabled 43 multiprocess bool // multiprocess extensions are active 44 maxTransmitAttempts int // maximum number of transmit or receive attempts when bad checksums are read 45 threadSuffixSupported bool // thread suffix supported by stub 46 isDebugserver bool // true if the stub is debugserver 47 xcmdok bool // x command can be used to transfer memory 48 goarch string 49 goos string 50 51 useXcmd bool // forces writeMemory to use the 'X' command 52 53 isUndoServer bool // true if using an Undo backend 54 55 log *logrus.Entry 56 } 57 58 var ErrTooManyAttempts = errors.New("too many transmit attempts") 59 60 // GdbProtocolError is an error response (Exx) of Gdb Remote Serial Protocol 61 // or an "unsupported command" response (empty packet). 62 type GdbProtocolError struct { 63 context string 64 cmd string 65 code string 66 } 67 68 func (err *GdbProtocolError) Error() string { 69 cmd := err.cmd 70 if len(cmd) > 20 { 71 cmd = cmd[:20] + "..." 72 } 73 if err.code == "" { 74 return fmt.Sprintf("unsupported packet %s during %s", cmd, err.context) 75 } 76 return fmt.Sprintf("protocol error %s during %s for packet %s", err.code, err.context, cmd) 77 } 78 79 func isProtocolErrorUnsupported(err error) bool { 80 gdberr, ok := err.(*GdbProtocolError) 81 if !ok { 82 return false 83 } 84 return gdberr.code == "" 85 } 86 87 // GdbMalformedThreadIDError is returned when a the stub responds with a 88 // thread ID that does not conform with the Gdb Remote Serial Protocol 89 // specification. 90 type GdbMalformedThreadIDError struct { 91 tid string 92 } 93 94 func (err *GdbMalformedThreadIDError) Error() string { 95 return fmt.Sprintf("malformed thread ID %q", err.tid) 96 } 97 98 const ( 99 qSupportedSimple = "$qSupported:swbreak+;hwbreak+;no-resumed+;xmlRegisters=i386" 100 qSupportedMultiprocess = "$qSupported:multiprocess+;swbreak+;hwbreak+;no-resumed+;xmlRegisters=i386" 101 ) 102 103 func (conn *gdbConn) handshake(regnames *gdbRegnames) error { 104 conn.ack = true 105 conn.packetSize = 256 106 conn.rdr = bufio.NewReader(conn.conn) 107 108 // This first ack packet is needed to start up the connection 109 conn.sendack('+') 110 111 conn.disableAck() 112 113 // Try to enable thread suffixes for the command 'g' and 'p' 114 if _, err := conn.exec([]byte("$QThreadSuffixSupported"), "init"); err != nil { 115 if isProtocolErrorUnsupported(err) { 116 conn.threadSuffixSupported = false 117 } else { 118 return err 119 } 120 } else { 121 conn.threadSuffixSupported = true 122 } 123 124 if !conn.threadSuffixSupported { 125 features, err := conn.qSupported(true) 126 if err != nil { 127 return err 128 } 129 conn.multiprocess = features["multiprocess"] 130 131 // for some reason gdbserver won't let us read target.xml unless first we 132 // select a thread. 133 if conn.multiprocess { 134 conn.exec([]byte("$Hgp0.0"), "init") 135 } else { 136 conn.exec([]byte("$Hgp0"), "init") 137 } 138 } else { 139 // execute qSupported with the multiprocess feature disabled (the 140 // interaction of thread suffixes and multiprocess is not documented), we 141 // only need this call to configure conn.packetSize. 142 if _, err := conn.qSupported(false); err != nil { 143 return err 144 } 145 } 146 147 // Attempt to figure out the name of the processor register. 148 // We either need qXfer:features:read (gdbserver/rr) or qRegisterInfo (lldb) 149 regFound := map[string]bool{ 150 regnames.PC: false, 151 regnames.SP: false, 152 regnames.BP: false, 153 regnames.CX: false, 154 } 155 if err := conn.readRegisterInfo(regFound); err != nil { 156 if isProtocolErrorUnsupported(err) { 157 if err := conn.readTargetXml(regFound); err != nil { 158 return err 159 } 160 } else { 161 return err 162 } 163 } 164 for n := range regFound { 165 if n == "" { 166 continue 167 } 168 if !regFound[n] { 169 return fmt.Errorf("could not find %s register", n) 170 } 171 } 172 173 // We either need: 174 // * QListThreadsInStopReply + qThreadStopInfo (i.e. lldb-server/debugserver), 175 // * or a stub that runs the inferior in single threaded mode (i.e. rr). 176 // Otherwise we'll have problems handling breakpoints in multithreaded programs. 177 if _, err := conn.exec([]byte("$QListThreadsInStopReply"), "init"); err != nil { 178 gdberr, ok := err.(*GdbProtocolError) 179 if !ok { 180 return err 181 } 182 if gdberr.code != "" { 183 return err 184 } 185 } 186 187 if resp, err := conn.exec([]byte("$x0,0"), "init"); err == nil && string(resp) == "OK" { 188 conn.xcmdok = true 189 } 190 191 return nil 192 } 193 194 // qSupported interprets qSupported responses. 195 func (conn *gdbConn) qSupported(multiprocess bool) (features map[string]bool, err error) { 196 q := qSupportedSimple 197 if multiprocess { 198 q = qSupportedMultiprocess 199 } 200 respBuf, err := conn.exec([]byte(q), "init/qSupported") 201 if err != nil { 202 return nil, err 203 } 204 resp := strings.Split(string(respBuf), ";") 205 features = make(map[string]bool) 206 for _, stubfeature := range resp { 207 if len(stubfeature) <= 0 { 208 continue 209 } else if equal := strings.Index(stubfeature, "="); equal >= 0 { 210 if stubfeature[:equal] == "PacketSize" { 211 if n, err := strconv.ParseInt(stubfeature[equal+1:], 16, 64); err == nil { 212 conn.packetSize = int(n) 213 } 214 } 215 } else if stubfeature[len(stubfeature)-1] == '+' { 216 features[stubfeature[:len(stubfeature)-1]] = true 217 } 218 } 219 return features, nil 220 } 221 222 // disableAck disables protocol acks. 223 func (conn *gdbConn) disableAck() error { 224 _, err := conn.exec([]byte("$QStartNoAckMode"), "init/disableAck") 225 if err == nil { 226 conn.ack = false 227 } 228 return err 229 } 230 231 // gdbTarget is a struct type used to parse target.xml 232 type gdbTarget struct { 233 Includes []gdbTargetInclude `xml:"xi include"` 234 Registers []gdbRegisterInfo `xml:"reg"` 235 } 236 237 type gdbTargetInclude struct { 238 Href string `xml:"href,attr"` 239 } 240 241 type gdbRegisterInfo struct { 242 Name string `xml:"name,attr"` 243 Bitsize int `xml:"bitsize,attr"` 244 Offset int 245 Regnum int `xml:"regnum,attr"` 246 Group string `xml:"group,attr"` 247 248 ignoreOnWrite bool 249 } 250 251 func setRegFound(regFound map[string]bool, name string) { 252 for n := range regFound { 253 if name == n { 254 regFound[n] = true 255 } 256 } 257 } 258 259 // readTargetXml reads target.xml file from stub using qXfer:features:read, 260 // then parses it requesting any additional files. 261 // The schema of target.xml is described by: 262 // 263 // https://github.com/bminor/binutils-gdb/blob/61baf725eca99af2569262d10aca03dcde2698f6/gdb/features/gdb-target.dtd 264 func (conn *gdbConn) readTargetXml(regFound map[string]bool) (err error) { 265 conn.regsInfo, err = conn.readAnnex("target.xml") 266 if err != nil { 267 return err 268 } 269 var offset int 270 regnum := 0 271 for i := range conn.regsInfo { 272 if conn.regsInfo[i].Regnum == 0 { 273 conn.regsInfo[i].Regnum = regnum 274 } else { 275 regnum = conn.regsInfo[i].Regnum 276 } 277 conn.regsInfo[i].Offset = offset 278 offset += conn.regsInfo[i].Bitsize / 8 279 280 setRegFound(regFound, conn.regsInfo[i].Name) 281 regnum++ 282 } 283 284 return nil 285 } 286 287 // readRegisterInfo uses qRegisterInfo to read register information (used 288 // when qXfer:feature:read is not supported). 289 func (conn *gdbConn) readRegisterInfo(regFound map[string]bool) (err error) { 290 regnum := 0 291 for { 292 conn.outbuf.Reset() 293 fmt.Fprintf(&conn.outbuf, "$qRegisterInfo%x", regnum) 294 respbytes, err := conn.exec(conn.outbuf.Bytes(), "register info") 295 if err != nil { 296 if regnum == 0 { 297 return err 298 } 299 break 300 } 301 302 var regname string 303 var offset int 304 var bitsize int 305 var contained bool 306 var ignoreOnWrite bool 307 308 resp := string(respbytes) 309 for { 310 semicolon := strings.Index(resp, ";") 311 keyval := resp 312 if semicolon >= 0 { 313 keyval = resp[:semicolon] 314 } 315 316 colon := strings.Index(keyval, ":") 317 if colon >= 0 { 318 name := keyval[:colon] 319 value := keyval[colon+1:] 320 321 switch name { 322 case "name": 323 regname = value 324 case "offset": 325 offset, _ = strconv.Atoi(value) 326 case "bitsize": 327 bitsize, _ = strconv.Atoi(value) 328 case "container-regs": 329 contained = true 330 case "set": 331 if value == "Exception State Registers" || value == "AMX Registers" { 332 // debugserver doesn't like it if we try to write these 333 ignoreOnWrite = true 334 } 335 } 336 } 337 338 if semicolon < 0 { 339 break 340 } 341 resp = resp[semicolon+1:] 342 } 343 344 if contained { 345 if regname == "xmm0" { 346 conn.workaroundReg = &gdbRegisterInfo{Regnum: regnum, Name: regname, Bitsize: bitsize, Offset: offset, ignoreOnWrite: ignoreOnWrite} 347 } 348 regnum++ 349 continue 350 } 351 352 setRegFound(regFound, regname) 353 354 conn.regsInfo = append(conn.regsInfo, gdbRegisterInfo{Regnum: regnum, Name: regname, Bitsize: bitsize, Offset: offset, ignoreOnWrite: ignoreOnWrite}) 355 356 regnum++ 357 } 358 359 return nil 360 } 361 362 func (conn *gdbConn) readAnnex(annex string) ([]gdbRegisterInfo, error) { 363 tgtbuf, err := conn.qXfer("features", annex, false) 364 if err != nil { 365 return nil, err 366 } 367 var tgt gdbTarget 368 if err := xml.Unmarshal(tgtbuf, &tgt); err != nil { 369 return nil, err 370 } 371 372 for _, incl := range tgt.Includes { 373 regs, err := conn.readAnnex(incl.Href) 374 if err != nil { 375 return nil, err 376 } 377 tgt.Registers = append(tgt.Registers, regs...) 378 } 379 return tgt.Registers, nil 380 } 381 382 func (conn *gdbConn) readExecFile() (string, error) { 383 outbuf, err := conn.qXfer("exec-file", "", true) 384 if err != nil { 385 return "", err 386 } 387 return string(outbuf), nil 388 } 389 390 func (conn *gdbConn) readAuxv() ([]byte, error) { 391 return conn.qXfer("auxv", "", true) 392 } 393 394 // qXfer executes a 'qXfer' read with the specified kind (i.e. feature, 395 // exec-file, etc...) and annex. 396 func (conn *gdbConn) qXfer(kind, annex string, binary bool) ([]byte, error) { 397 out := []byte{} 398 for { 399 cmd := []byte(fmt.Sprintf("$qXfer:%s:read:%s:%x,fff", kind, annex, len(out))) 400 err := conn.send(cmd) 401 if err != nil { 402 return nil, err 403 } 404 buf, err := conn.recv(cmd, "target features transfer", binary) 405 if err != nil { 406 return nil, err 407 } 408 409 out = append(out, buf[1:]...) 410 if buf[0] == 'l' { 411 break 412 } 413 } 414 return out, nil 415 } 416 417 // qXferWrite executes a 'qXfer' write with the specified kind and annex. 418 func (conn *gdbConn) qXferWrite(kind, annex string) error { 419 conn.outbuf.Reset() 420 fmt.Fprintf(&conn.outbuf, "$qXfer:%s:write:%s:0:", kind, annex) 421 //TODO(aarzilli): if we ever actually need to write something with qXfer, 422 //this will need to be implemented properly. At the moment it is only used 423 //for a fake write to the siginfo kind, to end a diversion in 'rr'. 424 _, err := conn.exec(conn.outbuf.Bytes(), "qXfer") 425 return err 426 } 427 428 type breakpointType uint8 429 430 const ( 431 swBreakpoint breakpointType = 0 432 hwBreakpoint breakpointType = 1 433 writeWatchpoint breakpointType = 2 434 readWatchpoint breakpointType = 3 435 accessWatchpoint breakpointType = 4 436 ) 437 438 // setBreakpoint executes a 'Z' (insert breakpoint) command of type '0' and kind '1' or '4' 439 func (conn *gdbConn) setBreakpoint(addr uint64, typ breakpointType, kind int) error { 440 conn.outbuf.Reset() 441 fmt.Fprintf(&conn.outbuf, "$Z%d,%x,%d", typ, addr, kind) 442 _, err := conn.exec(conn.outbuf.Bytes(), "set breakpoint") 443 return err 444 } 445 446 // clearBreakpoint executes a 'z' (remove breakpoint) command of type '0' and kind '1' or '4' 447 func (conn *gdbConn) clearBreakpoint(addr uint64, typ breakpointType, kind int) error { 448 conn.outbuf.Reset() 449 fmt.Fprintf(&conn.outbuf, "$z%d,%x,%d", typ, addr, kind) 450 _, err := conn.exec(conn.outbuf.Bytes(), "clear breakpoint") 451 return err 452 } 453 454 // kill executes a 'k' (kill) command. 455 func (conn *gdbConn) kill() error { 456 resp, err := conn.exec([]byte{'$', 'k'}, "kill") 457 if err == io.EOF { 458 // The stub is allowed to shut the connection on us immediately after a 459 // kill. This is not an error. 460 conn.conn.Close() 461 conn.conn = nil 462 return proc.ErrProcessExited{Pid: conn.pid} 463 } 464 if err != nil { 465 return err 466 } 467 _, _, err = conn.parseStopPacket(resp, "", nil) 468 return err 469 } 470 471 // detach executes a 'D' (detach) command. 472 func (conn *gdbConn) detach() error { 473 if conn.conn == nil { 474 // Already detached 475 return nil 476 } 477 _, err := conn.exec([]byte{'$', 'D'}, "detach") 478 conn.conn.Close() 479 conn.conn = nil 480 return err 481 } 482 483 // readRegisters executes a 'g' (read registers) command. 484 func (conn *gdbConn) readRegisters(threadID string, data []byte) error { 485 if !conn.threadSuffixSupported { 486 if err := conn.selectThread('g', threadID, "registers read"); err != nil { 487 return err 488 } 489 } 490 conn.outbuf.Reset() 491 conn.outbuf.WriteString("$g") 492 conn.appendThreadSelector(threadID) 493 resp, err := conn.exec(conn.outbuf.Bytes(), "registers read") 494 if err != nil { 495 return err 496 } 497 498 for i := 0; i < len(resp); i += 2 { 499 n, _ := strconv.ParseUint(string(resp[i:i+2]), 16, 8) 500 data[i/2] = uint8(n) 501 } 502 503 return nil 504 } 505 506 // writeRegisters executes a 'G' (write registers) command. 507 func (conn *gdbConn) writeRegisters(threadID string, data []byte) error { 508 if !conn.threadSuffixSupported { 509 if err := conn.selectThread('g', threadID, "registers write"); err != nil { 510 return err 511 } 512 } 513 conn.outbuf.Reset() 514 conn.outbuf.WriteString("$G") 515 516 for _, b := range data { 517 fmt.Fprintf(&conn.outbuf, "%02x", b) 518 } 519 conn.appendThreadSelector(threadID) 520 _, err := conn.exec(conn.outbuf.Bytes(), "registers write") 521 return err 522 } 523 524 // readRegister executes 'p' (read register) command. 525 func (conn *gdbConn) readRegister(threadID string, regnum int, data []byte) error { 526 if !conn.threadSuffixSupported { 527 if err := conn.selectThread('g', threadID, "registers write"); err != nil { 528 return err 529 } 530 } 531 conn.outbuf.Reset() 532 fmt.Fprintf(&conn.outbuf, "$p%x", regnum) 533 conn.appendThreadSelector(threadID) 534 resp, err := conn.exec(conn.outbuf.Bytes(), "register read") 535 if err != nil { 536 return err 537 } 538 539 for i := 0; i < len(resp); i += 2 { 540 n, _ := strconv.ParseUint(string(resp[i:i+2]), 16, 8) 541 data[i/2] = uint8(n) 542 } 543 544 return nil 545 } 546 547 // writeRegister executes 'P' (write register) command. 548 func (conn *gdbConn) writeRegister(threadID string, regnum int, data []byte) error { 549 if !conn.threadSuffixSupported { 550 if err := conn.selectThread('g', threadID, "registers write"); err != nil { 551 return err 552 } 553 } 554 conn.outbuf.Reset() 555 fmt.Fprintf(&conn.outbuf, "$P%x=", regnum) 556 for _, b := range data { 557 fmt.Fprintf(&conn.outbuf, "%02x", b) 558 } 559 conn.appendThreadSelector(threadID) 560 _, err := conn.exec(conn.outbuf.Bytes(), "register write") 561 return err 562 } 563 564 // resume execution of the target process. 565 // If the current direction is proc.Backward this is done with the 'bc' command. 566 // If the current direction is proc.Forward this is done with the vCont command. 567 // The threads argument will be used to determine which signal to use to 568 // resume each thread. If a thread has sig == 0 the 'c' action will be used, 569 // otherwise the 'C' action will be used and the value of sig will be passed 570 // to it. 571 func (conn *gdbConn) resume(cctx *proc.ContinueOnceContext, threads map[int]*gdbThread, tu *threadUpdater) (stopPacket, error) { 572 if conn.direction == proc.Forward { 573 conn.outbuf.Reset() 574 fmt.Fprintf(&conn.outbuf, "$vCont") 575 for _, th := range threads { 576 if th.sig != 0 { 577 fmt.Fprintf(&conn.outbuf, ";C%02x:%s", th.sig, th.strID) 578 } 579 } 580 fmt.Fprintf(&conn.outbuf, ";c") 581 } else { 582 if err := conn.selectThread('c', "p-1.-1", "resume"); err != nil { 583 return stopPacket{}, err 584 } 585 conn.outbuf.Reset() 586 fmt.Fprint(&conn.outbuf, "$bc") 587 } 588 cctx.StopMu.Lock() 589 if err := conn.send(conn.outbuf.Bytes()); err != nil { 590 cctx.StopMu.Unlock() 591 return stopPacket{}, err 592 } 593 conn.running = true 594 cctx.StopMu.Unlock() 595 defer func() { 596 cctx.StopMu.Lock() 597 conn.running = false 598 cctx.StopMu.Unlock() 599 }() 600 if cctx.ResumeChan != nil { 601 close(cctx.ResumeChan) 602 cctx.ResumeChan = nil 603 } 604 return conn.waitForvContStop("resume", "-1", tu) 605 } 606 607 // step executes a 'vCont' command on the specified thread with 's' action. 608 func (conn *gdbConn) step(th *gdbThread, tu *threadUpdater, ignoreFaultSignal bool) error { 609 threadID := th.strID 610 if conn.direction != proc.Forward { 611 if err := conn.selectThread('c', threadID, "step"); err != nil { 612 return err 613 } 614 conn.outbuf.Reset() 615 fmt.Fprint(&conn.outbuf, "$bs") 616 if err := conn.send(conn.outbuf.Bytes()); err != nil { 617 return err 618 } 619 _, err := conn.waitForvContStop("singlestep", threadID, tu) 620 return err 621 } 622 623 var _SIGBUS uint8 624 switch conn.goos { 625 case "linux": 626 _SIGBUS = 0x7 627 case "darwin": 628 _SIGBUS = 0xa 629 default: 630 panic(fmt.Errorf("unknown GOOS %s", conn.goos)) 631 } 632 633 var sig uint8 = 0 634 for { 635 conn.outbuf.Reset() 636 if sig == 0 { 637 fmt.Fprintf(&conn.outbuf, "$vCont;s:%s", threadID) 638 } else { 639 fmt.Fprintf(&conn.outbuf, "$vCont;S%02x:%s", sig, threadID) 640 } 641 if err := conn.send(conn.outbuf.Bytes()); err != nil { 642 return err 643 } 644 if tu != nil { 645 tu.Reset() 646 } 647 sp, err := conn.waitForvContStop("singlestep", threadID, tu) 648 sig = sp.sig 649 if err != nil { 650 return err 651 } 652 switch sig { 653 case faultSignal: 654 if ignoreFaultSignal { // we attempting to read the TLS, a fault here should be ignored 655 return nil 656 } 657 case _SIGILL, _SIGBUS, _SIGFPE: 658 // propagate these signals to inferior immediately 659 case interruptSignal, breakpointSignal, stopSignal: 660 return nil 661 case childSignal: // stop on debugserver but SIGCHLD on lldb-server/linux 662 if conn.isDebugserver { 663 return nil 664 } 665 case debugServerTargetExcBadAccess, debugServerTargetExcBadInstruction, debugServerTargetExcArithmetic, debugServerTargetExcEmulation, debugServerTargetExcSoftware, debugServerTargetExcBreakpoint: 666 if ignoreFaultSignal { 667 return nil 668 } 669 return machTargetExcToError(sig) 670 default: 671 // delay propagation of any other signal to until after the stepping is done 672 th.sig = sig 673 sig = 0 674 } 675 } 676 } 677 678 var errThreadBlocked = errors.New("thread blocked") 679 680 func (conn *gdbConn) waitForvContStop(context, threadID string, tu *threadUpdater) (stopPacket, error) { 681 count := 0 682 failed := false 683 for { 684 conn.conn.SetReadDeadline(time.Now().Add(heartbeatInterval)) 685 resp, err := conn.recv(nil, context, false) 686 conn.conn.SetReadDeadline(time.Time{}) 687 if neterr, isneterr := err.(net.Error); isneterr && neterr.Timeout() { 688 // Debugserver sometimes forgets to inform us that inferior stopped, 689 // sending this status request after a timeout helps us get unstuck. 690 // Debugserver will not respond to this request unless inferior is 691 // already stopped. 692 if conn.isDebugserver { 693 conn.send([]byte("$?")) 694 } 695 if count > 1 && context == "singlestep" { 696 failed = true 697 conn.sendCtrlC() 698 } 699 count++ 700 } else if failed { 701 return stopPacket{}, errThreadBlocked 702 } else if err != nil { 703 return stopPacket{}, err 704 } else { 705 repeat, sp, err := conn.parseStopPacket(resp, threadID, tu) 706 if !repeat { 707 return sp, err 708 } 709 } 710 } 711 } 712 713 type stopPacket struct { 714 threadID string 715 sig uint8 716 reason string 717 watchAddr uint64 718 } 719 720 // Mach exception codes used to decode metype/medata keys in stop packets (necessary to support watchpoints with debugserver). 721 // See: 722 // 723 // https://opensource.apple.com/source/xnu/xnu-4570.1.46/osfmk/mach/exception_types.h.auto.html 724 // https://opensource.apple.com/source/xnu/xnu-4570.1.46/osfmk/mach/i386/exception.h.auto.html 725 // https://opensource.apple.com/source/xnu/xnu-4570.1.46/osfmk/mach/arm/exception.h.auto.html 726 const ( 727 _EXC_BREAKPOINT = 6 // mach exception type for hardware breakpoints 728 _EXC_I386_SGL = 1 // mach exception code for single step on x86, for some reason this is also used for watchpoints 729 _EXC_ARM_DA_DEBUG = 0x102 // mach exception code for debug fault on arm/arm64 730 ) 731 732 // executes 'vCont' (continue/step) command 733 func (conn *gdbConn) parseStopPacket(resp []byte, threadID string, tu *threadUpdater) (repeat bool, sp stopPacket, err error) { 734 switch resp[0] { 735 case 'T': 736 if len(resp) < 3 { 737 return false, stopPacket{}, fmt.Errorf("malformed response for vCont %s", string(resp)) 738 } 739 740 sig, err := strconv.ParseUint(string(resp[1:3]), 16, 8) 741 if err != nil { 742 return false, stopPacket{}, fmt.Errorf("malformed stop packet: %s", string(resp)) 743 } 744 sp.sig = uint8(sig) 745 746 if logflags.GdbWire() && gdbWireFullStopPacket { 747 conn.log.Debugf("full stop packet: %s", string(resp)) 748 } 749 750 var metype int 751 var medata = make([]uint64, 0, 10) 752 753 buf := resp[3:] 754 for buf != nil { 755 colon := bytes.Index(buf, []byte{':'}) 756 if colon < 0 { 757 break 758 } 759 key := buf[:colon] 760 buf = buf[colon+1:] 761 762 semicolon := bytes.Index(buf, []byte{';'}) 763 var value []byte 764 if semicolon < 0 { 765 value = buf 766 buf = nil 767 } else { 768 value = buf[:semicolon] 769 buf = buf[semicolon+1:] 770 } 771 772 switch string(key) { 773 case "thread": 774 sp.threadID = string(value) 775 case "threads": 776 if tu != nil { 777 tu.Add(strings.Split(string(value), ",")) 778 tu.Finish() 779 } 780 case "reason": 781 sp.reason = string(value) 782 case "watch", "awatch", "rwatch": 783 sp.watchAddr, err = strconv.ParseUint(string(value), 16, 64) 784 if err != nil { 785 return false, stopPacket{}, fmt.Errorf("malformed stop packet: %s (wrong watch address)", string(resp)) 786 } 787 case "metype": 788 // mach exception type (debugserver extension) 789 metype, _ = strconv.Atoi(string(value)) 790 case "medata": 791 // mach exception data (debugserver extension) 792 d, _ := strconv.ParseUint(string(value), 16, 64) 793 medata = append(medata, d) 794 } 795 } 796 797 // Debugserver does not report watchpoint stops in the standard way preferring 798 // instead the semi-undocumented metype/medata keys. 799 // These values also have different meanings depending on the CPU architecture. 800 switch conn.goarch { 801 case "amd64": 802 if metype == _EXC_BREAKPOINT && len(medata) >= 2 && medata[0] == _EXC_I386_SGL { 803 sp.watchAddr = medata[1] // this should be zero if this is really a single step stop and non-zero for watchpoints 804 } 805 case "arm64": 806 if metype == _EXC_BREAKPOINT && len(medata) >= 2 && medata[0] == _EXC_ARM_DA_DEBUG { 807 sp.watchAddr = medata[1] 808 } 809 } 810 811 if syscall.Signal(sig) == syscall.SIGCHLD { 812 // FIXME get exit code 813 return false, stopPacket{}, proc.ErrProcessExited{Pid: conn.pid, Status: 0} 814 } 815 return false, sp, nil 816 817 case 'W', 'X': 818 // process exited, next two character are exit code 819 820 semicolon := bytes.Index(resp, []byte{';'}) 821 822 if semicolon < 0 { 823 semicolon = len(resp) 824 } 825 status, _ := strconv.ParseUint(string(resp[1:semicolon]), 16, 8) 826 return false, stopPacket{}, proc.ErrProcessExited{Pid: conn.pid, Status: int(status)} 827 828 case 'N': 829 // we were singlestepping the thread and the thread exited 830 sp.threadID = threadID 831 return false, sp, nil 832 833 case 'O': 834 data := make([]byte, 0, len(resp[1:])/2) 835 for i := 1; i < len(resp); i += 2 { 836 n, _ := strconv.ParseUint(string(resp[i:i+2]), 16, 8) 837 data = append(data, uint8(n)) 838 } 839 os.Stdout.Write(data) 840 return true, sp, nil 841 842 default: 843 return false, sp, fmt.Errorf("unexpected response for vCont %c", resp[0]) 844 } 845 } 846 847 const ctrlC = 0x03 // the ASCII character for ^C 848 849 // executes a ctrl-C on the line 850 func (conn *gdbConn) sendCtrlC() error { 851 conn.log.Debug("<- interrupt") 852 _, err := conn.conn.Write([]byte{ctrlC}) 853 return err 854 } 855 856 // queryProcessInfo executes a qProcessInfoPID (if pid != 0) or a qProcessInfo (if pid == 0) 857 func (conn *gdbConn) queryProcessInfo(pid int) (map[string]string, error) { 858 conn.outbuf.Reset() 859 if pid != 0 { 860 fmt.Fprintf(&conn.outbuf, "$qProcessInfoPID:%d", pid) 861 } else { 862 fmt.Fprint(&conn.outbuf, "$qProcessInfo") 863 } 864 resp, err := conn.exec(conn.outbuf.Bytes(), "process info for pid") 865 if err != nil { 866 return nil, err 867 } 868 869 pi := make(map[string]string) 870 871 for len(resp) > 0 { 872 semicolon := bytes.Index(resp, []byte{';'}) 873 keyval := resp 874 if semicolon >= 0 { 875 keyval = resp[:semicolon] 876 resp = resp[semicolon+1:] 877 } 878 879 colon := bytes.Index(keyval, []byte{':'}) 880 if colon < 0 { 881 continue 882 } 883 884 key := string(keyval[:colon]) 885 value := string(keyval[colon+1:]) 886 887 switch key { 888 case "name": 889 name := make([]byte, len(value)/2) 890 for i := 0; i < len(value); i += 2 { 891 n, _ := strconv.ParseUint(string(value[i:i+2]), 16, 8) 892 name[i/2] = byte(n) 893 } 894 pi[key] = string(name) 895 896 default: 897 pi[key] = value 898 } 899 } 900 return pi, nil 901 } 902 903 // executes qfThreadInfo/qsThreadInfo commands 904 func (conn *gdbConn) queryThreads(first bool) (threads []string, err error) { 905 // https://sourceware.org/gdb/onlinedocs/gdb/General-Query-Packets.html 906 conn.outbuf.Reset() 907 if first { 908 conn.outbuf.WriteString("$qfThreadInfo") 909 } else { 910 conn.outbuf.WriteString("$qsThreadInfo") 911 } 912 913 resp, err := conn.exec(conn.outbuf.Bytes(), "thread info") 914 if err != nil { 915 return nil, err 916 } 917 918 switch resp[0] { 919 case 'l': 920 return nil, nil 921 case 'm': 922 // parse list... 923 default: 924 return nil, errors.New("malformed qfThreadInfo response") 925 } 926 927 var pid int 928 resp = resp[1:] 929 for { 930 tidbuf := resp 931 comma := bytes.Index(tidbuf, []byte{','}) 932 if comma >= 0 { 933 tidbuf = tidbuf[:comma] 934 } 935 if conn.multiprocess && pid == 0 { 936 dot := bytes.Index(tidbuf, []byte{'.'}) 937 if dot >= 0 { 938 pid, _ = strconv.Atoi(string(tidbuf[1:dot])) 939 } 940 } 941 threads = append(threads, string(tidbuf)) 942 if comma < 0 { 943 break 944 } 945 resp = resp[comma+1:] 946 } 947 948 if conn.multiprocess && pid > 0 { 949 conn.pid = pid 950 } 951 return threads, nil 952 } 953 954 func (conn *gdbConn) selectThread(kind byte, threadID string, context string) error { 955 if conn.threadSuffixSupported { 956 panic("selectThread when thread suffix is supported") 957 } 958 conn.outbuf.Reset() 959 fmt.Fprintf(&conn.outbuf, "$H%c%s", kind, threadID) 960 _, err := conn.exec(conn.outbuf.Bytes(), context) 961 return err 962 } 963 964 func (conn *gdbConn) appendThreadSelector(threadID string) { 965 if !conn.threadSuffixSupported { 966 return 967 } 968 fmt.Fprintf(&conn.outbuf, ";thread:%s;", threadID) 969 } 970 971 func (conn *gdbConn) readMemory(data []byte, addr uint64) error { 972 if conn.xcmdok && len(data) > conn.packetSize { 973 return conn.readMemoryBinary(data, addr) 974 } 975 return conn.readMemoryHex(data, addr) 976 } 977 978 // executes 'm' (read memory) command 979 func (conn *gdbConn) readMemoryHex(data []byte, addr uint64) error { 980 size := len(data) 981 data = data[:0] 982 983 for size > 0 { 984 conn.outbuf.Reset() 985 986 // gdbserver will crash if we ask too many bytes... not return an error, actually crash 987 sz := size 988 if dataSize := (conn.packetSize - 4) / 2; sz > dataSize { 989 sz = dataSize 990 } 991 size = size - sz 992 993 fmt.Fprintf(&conn.outbuf, "$m%x,%x", addr+uint64(len(data)), sz) 994 resp, err := conn.exec(conn.outbuf.Bytes(), "memory read") 995 if err != nil { 996 return err 997 } 998 999 for i := 0; i < len(resp); i += 2 { 1000 n, _ := strconv.ParseUint(string(resp[i:i+2]), 16, 8) 1001 data = append(data, uint8(n)) 1002 } 1003 } 1004 return nil 1005 } 1006 1007 // executes 'x' (binary read memory) command 1008 func (conn *gdbConn) readMemoryBinary(data []byte, addr uint64) error { 1009 size := len(data) 1010 data = data[:0] 1011 1012 for len(data) < size { 1013 conn.outbuf.Reset() 1014 1015 sz := size - len(data) 1016 1017 fmt.Fprintf(&conn.outbuf, "$x%x,%x", addr+uint64(len(data)), sz) 1018 if err := conn.send(conn.outbuf.Bytes()); err != nil { 1019 return err 1020 } 1021 resp, err := conn.recv(conn.outbuf.Bytes(), "binary memory read", true) 1022 if err != nil { 1023 return err 1024 } 1025 data = append(data, resp...) 1026 } 1027 return nil 1028 } 1029 1030 func writeAsciiBytes(w io.Writer, data []byte) { 1031 for _, b := range data { 1032 fmt.Fprintf(w, "%02x", b) 1033 } 1034 } 1035 1036 // writeMemory writes memory using either 'M' or 'X' 1037 func (conn *gdbConn) writeMemory(addr uint64, data []byte) (written int, err error) { 1038 if conn.useXcmd { 1039 return conn.writeMemoryBinary(addr, data) 1040 } 1041 return conn.writeMemoryHex(addr, data) 1042 } 1043 1044 // executes 'M' (write memory) command 1045 func (conn *gdbConn) writeMemoryHex(addr uint64, data []byte) (written int, err error) { 1046 if len(data) == 0 { 1047 // LLDB can't parse requests for 0-length writes and hangs if we emit them 1048 return 0, nil 1049 } 1050 conn.outbuf.Reset() 1051 //TODO(aarzilli): do not send packets larger than conn.PacketSize 1052 fmt.Fprintf(&conn.outbuf, "$M%x,%x:", addr, len(data)) 1053 1054 writeAsciiBytes(&conn.outbuf, data) 1055 1056 _, err = conn.exec(conn.outbuf.Bytes(), "memory write") 1057 if err != nil { 1058 return 0, err 1059 } 1060 return len(data), nil 1061 } 1062 1063 func (conn *gdbConn) writeMemoryBinary(addr uint64, data []byte) (written int, err error) { 1064 conn.outbuf.Reset() 1065 fmt.Fprintf(&conn.outbuf, "$X%x,%x:", addr, len(data)) 1066 1067 for _, b := range data { 1068 switch b { 1069 case '#', '$', '}': 1070 conn.outbuf.WriteByte('}') 1071 conn.outbuf.WriteByte(b ^ escapeXor) 1072 default: 1073 conn.outbuf.WriteByte(b) 1074 } 1075 } 1076 1077 _, err = conn.exec(conn.outbuf.Bytes(), "memory write") 1078 if err != nil { 1079 return 0, err 1080 } 1081 return len(data), nil 1082 } 1083 1084 func (conn *gdbConn) allocMemory(sz uint64) (uint64, error) { 1085 conn.outbuf.Reset() 1086 fmt.Fprintf(&conn.outbuf, "$_M%x,rwx", sz) 1087 resp, err := conn.exec(conn.outbuf.Bytes(), "memory allocation") 1088 if err != nil { 1089 return 0, err 1090 } 1091 return strconv.ParseUint(string(resp), 16, 64) 1092 } 1093 1094 // threadStopInfo executes a 'qThreadStopInfo' and returns the reason the 1095 // thread stopped. 1096 func (conn *gdbConn) threadStopInfo(threadID string) (sp stopPacket, err error) { 1097 conn.outbuf.Reset() 1098 fmt.Fprintf(&conn.outbuf, "$qThreadStopInfo%s", threadID) 1099 resp, err := conn.exec(conn.outbuf.Bytes(), "thread stop info") 1100 if err != nil { 1101 return stopPacket{}, err 1102 } 1103 _, sp, err = conn.parseStopPacket(resp, "", nil) 1104 if err != nil { 1105 return stopPacket{}, err 1106 } 1107 if sp.threadID != threadID { 1108 // When we send a ^C (manual stop request) and the process is close to 1109 // stopping anyway, sometimes, debugserver will send back two stop 1110 // packets. We need to ignore this spurious stop packet. Because the first 1111 // thing we do after the stop is updateThreadList, which calls this 1112 // function, this is relatively painless. We simply need to check that the 1113 // stop packet we receive is for the thread we requested, if it isn't we 1114 // can assume it is the spurious extra stop packet and simply ignore it. 1115 // An example of a problematic interaction is in the commit message for 1116 // this change. 1117 // See https://github.com/go-delve/delve/issues/3013. 1118 1119 conn.conn.SetReadDeadline(time.Now().Add(10 * time.Millisecond)) 1120 resp, err = conn.recv(conn.outbuf.Bytes(), "thread stop info", false) 1121 conn.conn.SetReadDeadline(time.Time{}) 1122 if err != nil { 1123 if neterr, isneterr := err.(net.Error); isneterr && neterr.Timeout() { 1124 return stopPacket{}, fmt.Errorf("qThreadStopInfo mismatch, requested %s got %s", sp.threadID, threadID) 1125 } 1126 return stopPacket{}, err 1127 } 1128 _, sp, err = conn.parseStopPacket(resp, "", nil) 1129 if err != nil { 1130 return stopPacket{}, err 1131 } 1132 if sp.threadID != threadID { 1133 return stopPacket{}, fmt.Errorf("qThreadStopInfo mismatch, requested %s got %s", sp.threadID, threadID) 1134 } 1135 } 1136 1137 return sp, nil 1138 } 1139 1140 // restart executes a 'vRun' command. 1141 func (conn *gdbConn) restart(pos string) error { 1142 conn.outbuf.Reset() 1143 1144 if conn.isUndoServer { 1145 if pos != "" { 1146 fmt.Fprintf(&conn.outbuf, "$vUDB;goto_time;%s", pos) 1147 } else { 1148 // Find the actual min BB count. 1149 // TODO: is defaulting to zero if we can't get it correct? 1150 minBbCount := "0" 1151 1152 extent, err := conn.undoCmd("get_log_extent") 1153 if err != nil { 1154 return err 1155 } 1156 index := strings.Index(extent, ",") 1157 if index > 0 { 1158 minBbCount = extent[:index] 1159 } 1160 1161 conn.outbuf.Reset() 1162 fmt.Fprintf(&conn.outbuf, "$vUDB;goto_time;%s;0", minBbCount) 1163 } 1164 } else { 1165 fmt.Fprint(&conn.outbuf, "$vRun;") 1166 if pos != "" { 1167 fmt.Fprint(&conn.outbuf, ";") 1168 writeAsciiBytes(&conn.outbuf, []byte(pos)) 1169 } 1170 } 1171 _, err := conn.exec(conn.outbuf.Bytes(), "restart") 1172 return err 1173 } 1174 1175 // qRRCmd executes a qRRCmd command 1176 func (conn *gdbConn) qRRCmd(args ...string) (string, error) { 1177 if len(args) == 0 { 1178 panic("must specify at least one argument for qRRCmd") 1179 } 1180 conn.outbuf.Reset() 1181 fmt.Fprint(&conn.outbuf, "$qRRCmd") 1182 for _, arg := range args { 1183 fmt.Fprint(&conn.outbuf, ":") 1184 writeAsciiBytes(&conn.outbuf, []byte(arg)) 1185 } 1186 resp, err := conn.exec(conn.outbuf.Bytes(), "qRRCmd") 1187 if err != nil { 1188 return "", err 1189 } 1190 data := make([]byte, 0, len(resp)/2) 1191 for i := 0; i < len(resp); i += 2 { 1192 n, _ := strconv.ParseUint(string(resp[i:i+2]), 16, 8) 1193 data = append(data, uint8(n)) 1194 } 1195 return string(data), nil 1196 } 1197 1198 // undoCmd executes a vUDB command 1199 func (conn *gdbConn) undoCmd(args ...string) (string, error) { 1200 if len(args) == 0 { 1201 panic("must specify at least one argument for undoCmd") 1202 } 1203 conn.outbuf.Reset() 1204 fmt.Fprint(&conn.outbuf, "$vUDB") 1205 for _, arg := range args { 1206 fmt.Fprint(&conn.outbuf, ";", arg) 1207 } 1208 resp, err := conn.exec(conn.outbuf.Bytes(), "undoCmd") 1209 if err != nil { 1210 return "", err 1211 } 1212 return string(resp), nil 1213 } 1214 1215 type imageList struct { 1216 Images []imageDescription `json:"images"` 1217 } 1218 1219 type imageDescription struct { 1220 LoadAddress uint64 `json:"load_address"` 1221 Pathname string `json:"pathname"` 1222 MachHeader machHeader `json:"mach_header"` 1223 } 1224 1225 type machHeader struct { 1226 FileType macho.Type `json:"filetype"` 1227 } 1228 1229 // getLoadedDynamicLibraries executes jGetLoadedDynamicLibrariesInfos which 1230 // returns the list of loaded dynamic libraries 1231 func (conn *gdbConn) getLoadedDynamicLibraries() ([]imageDescription, error) { 1232 cmd := []byte("$jGetLoadedDynamicLibrariesInfos:{\"fetch_all_solibs\":true}") 1233 if err := conn.send(cmd); err != nil { 1234 return nil, err 1235 } 1236 resp, err := conn.recv(cmd, "get dynamic libraries", true) 1237 if err != nil { 1238 return nil, err 1239 } 1240 var images imageList 1241 err = json.Unmarshal(resp, &images) 1242 return images.Images, err 1243 } 1244 1245 type memoryRegionInfo struct { 1246 start uint64 1247 size uint64 1248 permissions string 1249 name string 1250 } 1251 1252 func decodeHexString(in []byte) (string, bool) { 1253 out := make([]byte, 0, len(in)/2) 1254 for i := 0; i < len(in); i += 2 { 1255 v, err := strconv.ParseUint(string(in[i:i+2]), 16, 8) 1256 if err != nil { 1257 return "", false 1258 } 1259 out = append(out, byte(v)) 1260 } 1261 return string(out), true 1262 } 1263 1264 func (conn *gdbConn) memoryRegionInfo(addr uint64) (*memoryRegionInfo, error) { 1265 conn.outbuf.Reset() 1266 fmt.Fprintf(&conn.outbuf, "$qMemoryRegionInfo:%x", addr) 1267 resp, err := conn.exec(conn.outbuf.Bytes(), "qMemoryRegionInfo") 1268 if err != nil { 1269 return nil, err 1270 } 1271 1272 mri := &memoryRegionInfo{} 1273 1274 buf := resp 1275 for len(buf) > 0 { 1276 colon := bytes.Index(buf, []byte{':'}) 1277 if colon < 0 { 1278 break 1279 } 1280 key := buf[:colon] 1281 buf = buf[colon+1:] 1282 1283 semicolon := bytes.Index(buf, []byte{';'}) 1284 var value []byte 1285 if semicolon < 0 { 1286 value = buf 1287 buf = nil 1288 } else { 1289 value = buf[:semicolon] 1290 buf = buf[semicolon+1:] 1291 } 1292 1293 switch string(key) { 1294 case "start": 1295 start, err := strconv.ParseUint(string(value), 16, 64) 1296 if err != nil { 1297 return nil, fmt.Errorf("malformed qMemoryRegionInfo response packet (start): %v in %s", err, string(resp)) 1298 } 1299 mri.start = start 1300 case "size": 1301 size, err := strconv.ParseUint(string(value), 16, 64) 1302 if err != nil { 1303 return nil, fmt.Errorf("malformed qMemoryRegionInfo response packet (size): %v in %s", err, string(resp)) 1304 } 1305 mri.size = size 1306 case "permissions": 1307 mri.permissions = string(value) 1308 case "name": 1309 namestr, ok := decodeHexString(value) 1310 if !ok { 1311 return nil, fmt.Errorf("malformed qMemoryRegionInfo response packet (name): %s", string(resp)) 1312 } 1313 mri.name = namestr 1314 case "error": 1315 errstr, ok := decodeHexString(value) 1316 if !ok { 1317 return nil, fmt.Errorf("malformed qMemoryRegionInfo response packet (error): %s", string(resp)) 1318 } 1319 return nil, fmt.Errorf("qMemoryRegionInfo error: %s", errstr) 1320 } 1321 } 1322 1323 return mri, nil 1324 } 1325 1326 // exec executes a message to the stub and reads a response. 1327 // The details of the wire protocol are described here: 1328 // 1329 // https://sourceware.org/gdb/onlinedocs/gdb/Overview.html#Overview 1330 func (conn *gdbConn) exec(cmd []byte, context string) ([]byte, error) { 1331 if err := conn.send(cmd); err != nil { 1332 return nil, err 1333 } 1334 return conn.recv(cmd, context, false) 1335 } 1336 1337 var hexdigit = []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'} 1338 1339 func (conn *gdbConn) send(cmd []byte) error { 1340 if len(cmd) == 0 || cmd[0] != '$' { 1341 panic("gdb protocol error: command doesn't start with '$'") 1342 } 1343 1344 // append checksum to packet 1345 cmd = append(cmd, '#') 1346 sum := checksum(cmd) 1347 cmd = append(cmd, hexdigit[sum>>4], hexdigit[sum&0xf]) 1348 1349 attempt := 0 1350 for { 1351 if logflags.GdbWire() { 1352 if len(cmd) > gdbWireMaxLen { 1353 conn.log.Debugf("<- %s...", string(cmd[:gdbWireMaxLen])) 1354 } else { 1355 conn.log.Debugf("<- %s", string(cmd)) 1356 } 1357 } 1358 _, err := conn.conn.Write(cmd) 1359 if err != nil { 1360 return err 1361 } 1362 1363 if !conn.ack { 1364 break 1365 } 1366 1367 if conn.readack() { 1368 break 1369 } 1370 if attempt > conn.maxTransmitAttempts { 1371 return ErrTooManyAttempts 1372 } 1373 attempt++ 1374 } 1375 return nil 1376 } 1377 1378 func (conn *gdbConn) recv(cmd []byte, context string, binary bool) (resp []byte, err error) { 1379 attempt := 0 1380 for { 1381 var err error 1382 resp, err = conn.rdr.ReadBytes('#') 1383 if err != nil { 1384 return nil, err 1385 } 1386 1387 // read checksum 1388 _, err = io.ReadFull(conn.rdr, conn.inbuf[:2]) 1389 if err != nil { 1390 return nil, err 1391 } 1392 if logflags.GdbWire() { 1393 out := resp 1394 partial := false 1395 if idx := bytes.Index(out, []byte{'\n'}); idx >= 0 && !binary { 1396 out = resp[:idx] 1397 partial = true 1398 } 1399 if len(out) > gdbWireMaxLen { 1400 out = out[:gdbWireMaxLen] 1401 partial = true 1402 } 1403 if !partial { 1404 if binary { 1405 conn.log.Debugf("-> %q%s", string(resp), string(conn.inbuf[:2])) 1406 } else { 1407 conn.log.Debugf("-> %s%s", string(resp), string(conn.inbuf[:2])) 1408 } 1409 } else { 1410 if binary { 1411 conn.log.Debugf("-> %q...", string(out)) 1412 } else { 1413 conn.log.Debugf("-> %s...", string(out)) 1414 } 1415 } 1416 } 1417 1418 if !conn.ack { 1419 break 1420 } 1421 1422 if resp[0] == '%' { 1423 // If the first character is a % (instead of $) the stub sent us a 1424 // notification packet, this is weird since we specifically claimed that 1425 // we don't support notifications of any kind, but it should be safe to 1426 // ignore regardless. 1427 continue 1428 } 1429 1430 if checksumok(resp, conn.inbuf[:2]) { 1431 conn.sendack('+') 1432 break 1433 } 1434 if attempt > conn.maxTransmitAttempts { 1435 conn.sendack('+') 1436 return nil, ErrTooManyAttempts 1437 } 1438 attempt++ 1439 conn.sendack('-') 1440 } 1441 1442 if binary { 1443 conn.inbuf, resp = binarywiredecode(resp, conn.inbuf) 1444 } else { 1445 conn.inbuf, resp = wiredecode(resp, conn.inbuf) 1446 } 1447 1448 if len(resp) == 0 || (resp[0] == 'E' && !binary) || (resp[0] == 'E' && len(resp) == 3) { 1449 cmdstr := "" 1450 if cmd != nil { 1451 cmdstr = string(cmd) 1452 } 1453 return nil, &GdbProtocolError{context, cmdstr, string(resp)} 1454 } 1455 1456 return resp, nil 1457 } 1458 1459 // Readack reads one byte from stub, returns true if the byte is '+' 1460 func (conn *gdbConn) readack() bool { 1461 b, err := conn.rdr.ReadByte() 1462 if err != nil { 1463 return false 1464 } 1465 conn.log.Debugf("-> %s", string(b)) 1466 return b == '+' 1467 } 1468 1469 // Sendack executes an ack character, c must be either '+' or '-' 1470 func (conn *gdbConn) sendack(c byte) { 1471 if c != '+' && c != '-' { 1472 panic(fmt.Errorf("sendack(%c)", c)) 1473 } 1474 conn.conn.Write([]byte{c}) 1475 conn.log.Debugf("<- %s", string(c)) 1476 } 1477 1478 // escapeXor is the value mandated by the specification to escape characters 1479 const escapeXor byte = 0x20 1480 1481 // wiredecode decodes the contents of in into buf. 1482 // If buf is nil it will be allocated ex-novo, if the size of buf is not 1483 // enough to hold the decoded contents it will be grown. 1484 // Returns the newly allocated buffer as newbuf and the message contents as 1485 // msg. 1486 func wiredecode(in, buf []byte) (newbuf, msg []byte) { 1487 if buf != nil { 1488 buf = buf[:0] 1489 } else { 1490 buf = make([]byte, 0, 256) 1491 } 1492 1493 start := 1 1494 1495 for i := 0; i < len(in); i++ { 1496 switch ch := in[i]; ch { 1497 case '{': // escape 1498 if i+1 >= len(in) { 1499 buf = append(buf, ch) 1500 } else { 1501 buf = append(buf, in[i+1]^escapeXor) 1502 i++ 1503 } 1504 case ':': 1505 buf = append(buf, ch) 1506 if i == 3 { 1507 // we just read the sequence identifier 1508 start = i + 1 1509 } 1510 case '#': // end of packet 1511 return buf, buf[start:] 1512 case '*': // runlength encoding marker 1513 if i+1 >= len(in) || i == 0 { 1514 buf = append(buf, ch) 1515 } else { 1516 n := in[i+1] - 29 1517 r := buf[len(buf)-1] 1518 for j := uint8(0); j < n; j++ { 1519 buf = append(buf, r) 1520 } 1521 i++ 1522 } 1523 default: 1524 buf = append(buf, ch) 1525 } 1526 } 1527 return buf, buf[start:] 1528 } 1529 1530 // binarywiredecode is like wiredecode but decodes the wire encoding for 1531 // binary packets, such as the 'x' and 'X' packets as well as all the json 1532 // packets used by lldb/debugserver. 1533 func binarywiredecode(in, buf []byte) (newbuf, msg []byte) { 1534 if buf != nil { 1535 buf = buf[:0] 1536 } else { 1537 buf = make([]byte, 0, 256) 1538 } 1539 1540 start := 1 1541 1542 for i := 0; i < len(in); i++ { 1543 switch ch := in[i]; ch { 1544 case '}': // escape 1545 if i+1 >= len(in) { 1546 buf = append(buf, ch) 1547 } else { 1548 buf = append(buf, in[i+1]^escapeXor) 1549 i++ 1550 } 1551 case '#': // end of packet 1552 return buf, buf[start:] 1553 default: 1554 buf = append(buf, ch) 1555 } 1556 } 1557 return buf, buf[start:] 1558 } 1559 1560 // Checksumok checks that checksum is a valid checksum for packet. 1561 func checksumok(packet, checksumBuf []byte) bool { 1562 if packet[0] != '$' { 1563 return false 1564 } 1565 1566 sum := checksum(packet) 1567 tgt, err := strconv.ParseUint(string(checksumBuf), 16, 8) 1568 if err != nil { 1569 return false 1570 } 1571 1572 tgt8 := uint8(tgt) 1573 1574 return sum == tgt8 1575 } 1576 1577 func checksum(packet []byte) (sum uint8) { 1578 for i := 1; i < len(packet); i++ { 1579 if packet[i] == '#' { 1580 return sum 1581 } 1582 sum += packet[i] 1583 } 1584 return sum 1585 }