github.com/undoio/delve@v1.9.0/pkg/proc/gdbserial/gdbserver.go (about) 1 // This file and its companion gdbserver_conn implement a target.Interface 2 // backed by a connection to a debugger speaking the "Gdb Remote Serial 3 // Protocol". 4 // 5 // The "Gdb Remote Serial Protocol" is a low level debugging protocol 6 // originally designed so that gdb could be used to debug programs running 7 // in embedded environments but it was later extended to support programs 8 // running on any environment and a variety of debuggers support it: 9 // gdbserver, lldb-server, macOS's debugserver and rr. 10 // 11 // The protocol is specified at: 12 // https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html 13 // with additional documentation for lldb specific extensions described at: 14 // https://github.com/llvm/llvm-project/blob/main/lldb/docs/lldb-gdb-remote.txt 15 // 16 // Terminology: 17 // * inferior: the program we are trying to debug 18 // * stub: the debugger on the other side of the protocol's connection (for 19 // example lldb-server) 20 // * gdbserver: stub version of gdb 21 // * lldb-server: stub version of lldb 22 // * debugserver: a different stub version of lldb, installed with lldb on 23 // macOS. 24 // * mozilla rr: a stub that records the full execution of a program 25 // and can then play it back. 26 // * undo: a stub that records the full execution of a program 27 // and can then play it back. 28 // 29 // Implementations of the protocol vary wildly between stubs, while there is 30 // a command to query the stub about supported features (qSupported) this 31 // only covers *some* of the more recent additions to the protocol and most 32 // of the older packets are optional and *not* implemented by all stubs. 33 // For example gdbserver implements 'g' (read all registers) but not 'p' 34 // (read single register) while lldb-server implements 'p' but not 'g'. 35 // 36 // The protocol is also underspecified with regards to how the stub should 37 // handle a multithreaded inferior. Its default mode of operation is 38 // "all-stop mode", when a thread hits a breakpoint all other threads are 39 // also stopped. But the protocol doesn't say what happens if a second 40 // thread hits a breakpoint while the stub is in the process of stopping all 41 // other threads. 42 // 43 // In practice the stub is allowed to swallow the second breakpoint hit or 44 // to return it at a later time. If the stub chooses the latter behavior 45 // (like gdbserver does) it is allowed to return delayed events on *any* 46 // vCont packet. This is incredibly inconvenient since if we get notified 47 // about a delayed breakpoint while we are trying to singlestep another 48 // thread it's impossible to know when the singlestep we requested ended. 49 // 50 // What this means is that gdbserver can only be supported for multithreaded 51 // inferiors by selecting non-stop mode, which behaves in a markedly 52 // different way from all-stop mode and isn't supported by anything except 53 // gdbserver. 54 // 55 // lldb-server/debugserver takes a different approach, only the first stop 56 // event is reported, if any other event happens "simultaneously" they are 57 // suppressed by the stub and the debugger can query for them using 58 // qThreadStopInfo. This is much easier for us to implement and the 59 // implementation gracefully degrades to the case where qThreadStopInfo is 60 // unavailable but the inferior is run in single threaded mode. 61 // 62 // Therefore the following code will assume lldb-server-like behavior. 63 64 package gdbserial 65 66 import ( 67 "debug/macho" 68 "encoding/binary" 69 "errors" 70 "fmt" 71 "net" 72 "os" 73 "os/exec" 74 "path/filepath" 75 "runtime" 76 "strconv" 77 "strings" 78 "sync" 79 "time" 80 81 isatty "github.com/mattn/go-isatty" 82 "github.com/undoio/delve/pkg/dwarf/op" 83 "github.com/undoio/delve/pkg/elfwriter" 84 "github.com/undoio/delve/pkg/logflags" 85 "github.com/undoio/delve/pkg/proc" 86 "github.com/undoio/delve/pkg/proc/internal/ebpf" 87 "github.com/undoio/delve/pkg/proc/linutil" 88 "github.com/undoio/delve/pkg/proc/macutil" 89 ) 90 91 const ( 92 gdbWireFullStopPacket = false 93 gdbWireMaxLen = 120 94 95 maxTransmitAttempts = 3 // number of retransmission attempts on failed checksum 96 initialInputBufferSize = 2048 // size of the input buffer for gdbConn 97 98 debugServerEnvVar = "DELVE_DEBUGSERVER_PATH" // use this environment variable to override the path to debugserver used by Launch/Attach 99 ) 100 101 const heartbeatInterval = 10 * time.Second 102 103 // Relative to $(xcode-select --print-path)/../ 104 // xcode-select typically returns the path to the Developer directory, which is a sibling to SharedFrameworks. 105 var debugserverXcodeRelativeExecutablePath = "SharedFrameworks/LLDB.framework/Versions/A/Resources/debugserver" 106 107 var debugserverExecutablePaths = []string{ 108 "debugserver", 109 "/Library/Developer/CommandLineTools/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/debugserver", 110 // Function returns the active developer directory provided by xcode-select to compute a debugserver path. 111 func() string { 112 if _, err := exec.LookPath("xcode-select"); err != nil { 113 return "" 114 } 115 116 stdout, err := exec.Command("xcode-select", "--print-path").Output() 117 if err != nil { 118 return "" 119 } 120 121 xcodePath := strings.TrimSpace(string(stdout)) 122 if xcodePath == "" { 123 return "" 124 } 125 126 // xcode-select prints the path to the active Developer directory, which is typically a sibling to SharedFrameworks. 127 return filepath.Join(xcodePath, "..", debugserverXcodeRelativeExecutablePath) 128 }(), 129 } 130 131 // ErrDirChange is returned when trying to change execution direction 132 // while there are still internal breakpoints set. 133 var ErrDirChange = errors.New("direction change with internal breakpoints") 134 135 // ErrStartCallInjectionBackwards is returned when trying to start a call 136 // injection while the recording is being run backwards. 137 var ErrStartCallInjectionBackwards = errors.New("can not start a call injection while running backwards") 138 139 var checkCanUnmaskSignalsOnce sync.Once 140 var canUnmaskSignalsCached bool 141 142 // gdbProcess implements proc.Process using a connection to a debugger stub 143 // that understands Gdb Remote Serial Protocol. 144 type gdbProcess struct { 145 bi *proc.BinaryInfo 146 regnames *gdbRegnames 147 conn gdbConn 148 149 threads map[int]*gdbThread 150 currentThread *gdbThread 151 152 exited, detached bool 153 almostExited bool // true if 'rr' has sent its synthetic SIGKILL 154 ctrlC bool // ctrl-c was sent to stop inferior 155 156 breakpoints proc.BreakpointMap 157 158 gcmdok bool // true if the stub supports g and (maybe) G commands 159 _Gcmdok bool // true if the stub supports G command 160 threadStopInfo bool // true if the stub supports qThreadStopInfo 161 tracedir string // if attached to rr the path to the trace directory 162 163 breakpointKind int // breakpoint kind to pass to 'z' and 'Z' when creating software breakpoints 164 165 process *os.Process 166 waitChan chan *os.ProcessState 167 168 onDetach func() // called after a successful detach 169 170 localCheckpointLastId int 171 localCheckpoints map[int]proc.Checkpoint 172 } 173 174 var _ proc.RecordingManipulationInternal = &gdbProcess{} 175 176 // gdbThread represents an operating system thread. 177 type gdbThread struct { 178 ID int 179 strID string 180 regs gdbRegisters 181 CurrentBreakpoint proc.BreakpointState 182 p *gdbProcess 183 sig uint8 // signal received by thread after last stop 184 setbp bool // thread was stopped because of a breakpoint 185 watchAddr uint64 // if > 0 this is the watchpoint address 186 common proc.CommonThread 187 } 188 189 // ErrBackendUnavailable is returned when the stub program can not be found. 190 type ErrBackendUnavailable struct{} 191 192 func (err *ErrBackendUnavailable) Error() string { 193 return "backend unavailable" 194 } 195 196 // gdbRegisters represents the current value of the registers of a thread. 197 // The storage space for all the registers is allocated as a single memory 198 // block in buf, the value field inside an individual gdbRegister will be a 199 // slice of the global buf field. 200 type gdbRegisters struct { 201 regs map[string]gdbRegister 202 regsInfo []gdbRegisterInfo 203 tls uint64 204 gaddr uint64 205 hasgaddr bool 206 buf []byte 207 arch *proc.Arch 208 regnames *gdbRegnames 209 } 210 211 type gdbRegister struct { 212 value []byte 213 regnum int 214 215 ignoreOnWrite bool 216 } 217 218 // gdbRegname records names of important CPU registers 219 type gdbRegnames struct { 220 PC, SP, BP, CX, FsBase string 221 } 222 223 // newProcess creates a new Process instance. 224 // If process is not nil it is the stub's process and will be killed after 225 // Detach. 226 // Use Listen, Dial or Connect to complete connection. 227 func newProcess(process *os.Process) *gdbProcess { 228 logger := logflags.GdbWireLogger() 229 p := &gdbProcess{ 230 conn: gdbConn{ 231 maxTransmitAttempts: maxTransmitAttempts, 232 inbuf: make([]byte, 0, initialInputBufferSize), 233 direction: proc.Forward, 234 log: logger, 235 goarch: runtime.GOARCH, 236 goos: runtime.GOOS, 237 }, 238 threads: make(map[int]*gdbThread), 239 bi: proc.NewBinaryInfo(runtime.GOOS, runtime.GOARCH), 240 regnames: new(gdbRegnames), 241 breakpoints: proc.NewBreakpointMap(), 242 gcmdok: true, 243 threadStopInfo: true, 244 process: process, 245 localCheckpointLastId: 1, 246 localCheckpoints: make(map[int]proc.Checkpoint), 247 } 248 249 switch p.bi.Arch.Name { 250 default: 251 fallthrough 252 case "amd64": 253 p.breakpointKind = 1 254 case "arm64": 255 p.breakpointKind = 4 256 } 257 258 p.regnames.PC = registerName(p.bi.Arch, p.bi.Arch.PCRegNum) 259 p.regnames.SP = registerName(p.bi.Arch, p.bi.Arch.SPRegNum) 260 p.regnames.BP = registerName(p.bi.Arch, p.bi.Arch.BPRegNum) 261 262 switch p.bi.Arch.Name { 263 case "arm64": 264 p.regnames.BP = "fp" 265 p.regnames.CX = "x0" 266 case "amd64": 267 p.regnames.CX = "rcx" 268 p.regnames.FsBase = "fs_base" 269 default: 270 panic("not implemented") 271 } 272 273 if process != nil { 274 p.waitChan = make(chan *os.ProcessState) 275 go func() { 276 state, _ := process.Wait() 277 p.waitChan <- state 278 }() 279 } 280 281 return p 282 } 283 284 // Listen waits for a connection from the stub. 285 func (p *gdbProcess) Listen(listener net.Listener, path string, pid int, debugInfoDirs []string, stopReason proc.StopReason) (*proc.Target, error) { 286 acceptChan := make(chan net.Conn) 287 288 go func() { 289 conn, _ := listener.Accept() 290 acceptChan <- conn 291 }() 292 293 select { 294 case conn := <-acceptChan: 295 listener.Close() 296 if conn == nil { 297 return nil, errors.New("could not connect") 298 } 299 return p.Connect(conn, path, pid, debugInfoDirs, stopReason) 300 case status := <-p.waitChan: 301 listener.Close() 302 return nil, fmt.Errorf("stub exited while waiting for connection: %v", status) 303 } 304 } 305 306 // Dial attempts to connect to the stub. 307 func (p *gdbProcess) Dial(addr string, path string, pid int, debugInfoDirs []string, stopReason proc.StopReason) (*proc.Target, error) { 308 for { 309 conn, err := net.Dial("tcp", addr) 310 if err == nil { 311 return p.Connect(conn, path, pid, debugInfoDirs, stopReason) 312 } 313 select { 314 case status := <-p.waitChan: 315 return nil, fmt.Errorf("stub exited while attempting to connect: %v", status) 316 default: 317 } 318 time.Sleep(time.Second) 319 } 320 } 321 322 // Connect connects to a stub and performs a handshake. 323 // 324 // Path and pid are, respectively, the path to the executable of the target 325 // program and the PID of the target process, both are optional, however 326 // some stubs do not provide ways to determine path and pid automatically 327 // and Connect will be unable to function without knowing them. 328 func (p *gdbProcess) Connect(conn net.Conn, path string, pid int, debugInfoDirs []string, stopReason proc.StopReason) (*proc.Target, error) { 329 p.conn.conn = conn 330 p.conn.pid = pid 331 err := p.conn.handshake(p.regnames) 332 if err != nil { 333 conn.Close() 334 return nil, err 335 } 336 337 if p.conn.isDebugserver { 338 // There are multiple problems with the 'g'/'G' commands on debugserver. 339 // On version 902 it used to crash the server completely (https://bugs.llvm.org/show_bug.cgi?id=36968), 340 // on arm64 it results in E74 being returned (https://bugs.llvm.org/show_bug.cgi?id=50169) 341 // and on systems where AVX-512 is used it returns the floating point 342 // registers scrambled and sometimes causes the mask registers to be 343 // zeroed out (https://github.com/go-delve/delve/pull/2498). 344 // All of these bugs stem from the fact that the main consumer of 345 // debugserver, lldb, never uses 'g' or 'G' which would make Delve the 346 // sole tester of those codepaths. 347 // Therefore we disable it here. The associated code is kept around to be 348 // used with Mozilla RR. 349 p.gcmdok = false 350 } 351 352 tgt, err := p.initialize(path, debugInfoDirs, stopReason) 353 if err != nil { 354 return nil, err 355 } 356 357 return tgt, nil 358 } 359 360 func (p *gdbProcess) SupportsBPF() bool { 361 return false 362 } 363 364 func (dbp *gdbProcess) GetBufferedTracepoints() []ebpf.RawUProbeParams { 365 return nil 366 } 367 368 func (dbp *gdbProcess) SetUProbe(fnName string, goidOffset int64, args []ebpf.UProbeArgMap) error { 369 panic("not implemented") 370 } 371 372 // unusedPort returns an unused tcp port 373 // This is a hack and subject to a race condition with other running 374 // programs, but most (all?) OS will cycle through all ephemeral ports 375 // before reassigning one port they just assigned, unless there's heavy 376 // churn in the ephemeral range this should work. 377 func unusedPort() string { 378 listener, err := net.Listen("tcp", "127.0.0.1:0") 379 if err != nil { 380 return ":8081" 381 } 382 port := listener.Addr().(*net.TCPAddr).Port 383 listener.Close() 384 return fmt.Sprintf(":%d", port) 385 } 386 387 // getDebugServerAbsolutePath returns a string of the absolute path to the debugserver binary IFF it is 388 // found in the system path ($PATH), the Xcode bundle or the standalone CLT location. 389 func getDebugServerAbsolutePath() string { 390 if path := os.Getenv(debugServerEnvVar); path != "" { 391 return path 392 } 393 for _, debugServerPath := range debugserverExecutablePaths { 394 if debugServerPath == "" { 395 continue 396 } 397 if _, err := exec.LookPath(debugServerPath); err == nil { 398 return debugServerPath 399 } 400 } 401 return "" 402 } 403 404 func canUnmaskSignals(debugServerExecutable string) bool { 405 checkCanUnmaskSignalsOnce.Do(func() { 406 buf, _ := exec.Command(debugServerExecutable, "--unmask-signals").CombinedOutput() 407 canUnmaskSignalsCached = !strings.Contains(string(buf), "unrecognized option") 408 }) 409 return canUnmaskSignalsCached 410 } 411 412 // commandLogger is a wrapper around the exec.Command() function to log the arguments prior to 413 // starting the process 414 func commandLogger(binary string, arguments ...string) *exec.Cmd { 415 logflags.GdbWireLogger().Debugf("executing %s %v", binary, arguments) 416 return exec.Command(binary, arguments...) 417 } 418 419 // ErrUnsupportedOS is returned when trying to use the lldb backend on Windows. 420 var ErrUnsupportedOS = errors.New("lldb backend not supported on Windows") 421 422 func getLdEnvVars() []string { 423 var result []string 424 425 environ := os.Environ() 426 for i := 0; i < len(environ); i++ { 427 if strings.HasPrefix(environ[i], "LD_") || 428 strings.HasPrefix(environ[i], "DYLD_") { 429 result = append(result, "-e", environ[i]) 430 } 431 } 432 433 return result 434 } 435 436 // LLDBLaunch starts an instance of lldb-server and connects to it, asking 437 // it to launch the specified target program with the specified arguments 438 // (cmd) on the specified directory wd. 439 func LLDBLaunch(cmd []string, wd string, flags proc.LaunchFlags, debugInfoDirs []string, tty string, redirects [3]string) (*proc.Target, error) { 440 if runtime.GOOS == "windows" { 441 return nil, ErrUnsupportedOS 442 } 443 if err := macutil.CheckRosetta(); err != nil { 444 return nil, err 445 } 446 447 foreground := flags&proc.LaunchForeground != 0 448 449 var ( 450 isDebugserver bool 451 listener net.Listener 452 port string 453 process *exec.Cmd 454 err error 455 hasRedirects bool 456 ) 457 458 if debugserverExecutable := getDebugServerAbsolutePath(); debugserverExecutable != "" { 459 listener, err = net.Listen("tcp", "127.0.0.1:0") 460 if err != nil { 461 return nil, err 462 } 463 ldEnvVars := getLdEnvVars() 464 args := make([]string, 0, len(cmd)+4+len(ldEnvVars)) 465 args = append(args, ldEnvVars...) 466 467 if tty != "" { 468 args = append(args, "--stdio-path", tty) 469 } else { 470 found := [3]bool{} 471 names := [3]string{"stdin", "stdout", "stderr"} 472 for i := range redirects { 473 if redirects[i] != "" { 474 found[i] = true 475 hasRedirects = true 476 args = append(args, fmt.Sprintf("--%s-path", names[i]), redirects[i]) 477 } 478 } 479 480 if foreground || hasRedirects { 481 for i := range found { 482 if !found[i] { 483 args = append(args, fmt.Sprintf("--%s-path", names[i]), "/dev/"+names[i]) 484 } 485 } 486 } 487 } 488 489 if logflags.LLDBServerOutput() { 490 args = append(args, "-g", "-l", "stdout") 491 } 492 if flags&proc.LaunchDisableASLR != 0 { 493 args = append(args, "-D") 494 } 495 if canUnmaskSignals(debugserverExecutable) { 496 args = append(args, "--unmask-signals") 497 } 498 args = append(args, "-F", "-R", fmt.Sprintf("127.0.0.1:%d", listener.Addr().(*net.TCPAddr).Port), "--") 499 args = append(args, cmd...) 500 501 isDebugserver = true 502 503 process = commandLogger(debugserverExecutable, args...) 504 } else { 505 if _, err = exec.LookPath("lldb-server"); err != nil { 506 return nil, &ErrBackendUnavailable{} 507 } 508 port = unusedPort() 509 args := make([]string, 0, len(cmd)+3) 510 args = append(args, "gdbserver", port, "--") 511 args = append(args, cmd...) 512 513 process = commandLogger("lldb-server", args...) 514 } 515 516 if logflags.LLDBServerOutput() || logflags.GdbWire() || foreground || hasRedirects { 517 process.Stdout = os.Stdout 518 process.Stderr = os.Stderr 519 } 520 if foreground || hasRedirects { 521 if isatty.IsTerminal(os.Stdin.Fd()) { 522 foregroundSignalsIgnore() 523 } 524 process.Stdin = os.Stdin 525 } 526 if wd != "" { 527 process.Dir = wd 528 } 529 530 if isatty.IsTerminal(os.Stdin.Fd()) { 531 process.SysProcAttr = sysProcAttr(foreground) 532 } 533 534 if runtime.GOOS == "darwin" { 535 process.Env = proc.DisableAsyncPreemptEnv() 536 } 537 538 if err = process.Start(); err != nil { 539 return nil, err 540 } 541 542 p := newProcess(process.Process) 543 p.conn.isDebugserver = isDebugserver 544 545 var tgt *proc.Target 546 if listener != nil { 547 tgt, err = p.Listen(listener, cmd[0], 0, debugInfoDirs, proc.StopLaunched) 548 } else { 549 tgt, err = p.Dial(port, cmd[0], 0, debugInfoDirs, proc.StopLaunched) 550 } 551 return tgt, err 552 } 553 554 // LLDBAttach starts an instance of lldb-server and connects to it, asking 555 // it to attach to the specified pid. 556 // Path is path to the target's executable, path only needs to be specified 557 // for some stubs that do not provide an automated way of determining it 558 // (for example debugserver). 559 func LLDBAttach(pid int, path string, debugInfoDirs []string) (*proc.Target, error) { 560 if runtime.GOOS == "windows" { 561 return nil, ErrUnsupportedOS 562 } 563 if err := macutil.CheckRosetta(); err != nil { 564 return nil, err 565 } 566 567 var ( 568 isDebugserver bool 569 process *exec.Cmd 570 listener net.Listener 571 port string 572 err error 573 ) 574 if debugserverExecutable := getDebugServerAbsolutePath(); debugserverExecutable != "" { 575 isDebugserver = true 576 listener, err = net.Listen("tcp", "127.0.0.1:0") 577 if err != nil { 578 return nil, err 579 } 580 args := []string{"-R", fmt.Sprintf("127.0.0.1:%d", listener.Addr().(*net.TCPAddr).Port), "--attach=" + strconv.Itoa(pid)} 581 if canUnmaskSignals(debugserverExecutable) { 582 args = append(args, "--unmask-signals") 583 } 584 process = commandLogger(debugserverExecutable, args...) 585 } else { 586 if _, err = exec.LookPath("lldb-server"); err != nil { 587 return nil, &ErrBackendUnavailable{} 588 } 589 port = unusedPort() 590 process = commandLogger("lldb-server", "gdbserver", "--attach", strconv.Itoa(pid), port) 591 } 592 593 process.Stdout = os.Stdout 594 process.Stderr = os.Stderr 595 process.SysProcAttr = sysProcAttr(false) 596 597 if err = process.Start(); err != nil { 598 return nil, err 599 } 600 601 p := newProcess(process.Process) 602 p.conn.isDebugserver = isDebugserver 603 604 var tgt *proc.Target 605 if listener != nil { 606 tgt, err = p.Listen(listener, path, pid, debugInfoDirs, proc.StopAttached) 607 } else { 608 tgt, err = p.Dial(port, path, pid, debugInfoDirs, proc.StopAttached) 609 } 610 return tgt, err 611 } 612 613 // EntryPoint will return the process entry point address, useful for 614 // debugging PIEs. 615 func (p *gdbProcess) EntryPoint() (uint64, error) { 616 var entryPoint uint64 617 if p.bi.GOOS == "darwin" && p.bi.Arch.Name == "arm64" { 618 // There is no auxv on darwin, however, we can get the location of the mach-o 619 // header from the debugserver by going through the loaded libraries, which includes 620 // the exe itself 621 images, _ := p.conn.getLoadedDynamicLibraries() 622 for _, image := range images { 623 if image.MachHeader.FileType == macho.TypeExec { 624 // This is a bit hacky. This is technically not the entrypoint, 625 // but rather we use the variable to points at the mach-o header, 626 // so we can get the offset in bininfo 627 entryPoint = image.LoadAddress 628 break 629 } 630 } 631 } else if auxv, err := p.conn.readAuxv(); err == nil { 632 // If we can't read the auxiliary vector it just means it's not supported 633 // by the OS or by the stub. If we are debugging a PIE and the entry point 634 // is needed proc.LoadBinaryInfo will complain about it. 635 entryPoint = linutil.EntryPointFromAuxv(auxv, p.BinInfo().Arch.PtrSize()) 636 } 637 638 return entryPoint, nil 639 } 640 641 // initialize uses qProcessInfo to load the inferior's PID and 642 // executable path. This command is not supported by all stubs and not all 643 // stubs will report both the PID and executable path. 644 func (p *gdbProcess) initialize(path string, debugInfoDirs []string, stopReason proc.StopReason) (*proc.Target, error) { 645 var err error 646 if path == "" { 647 // If we are attaching to a running process and the user didn't specify 648 // the executable file manually we must ask the stub for it. 649 // We support both qXfer:exec-file:read:: (the gdb way) and calling 650 // qProcessInfo (the lldb way). 651 // Unfortunately debugserver on macOS supports neither. 652 path, err = p.conn.readExecFile() 653 if err != nil { 654 if isProtocolErrorUnsupported(err) { 655 _, path, err = queryProcessInfo(p, p.Pid()) 656 if err != nil { 657 p.conn.conn.Close() 658 return nil, err 659 } 660 } else { 661 p.conn.conn.Close() 662 return nil, fmt.Errorf("could not determine executable path: %v", err) 663 } 664 } 665 } 666 667 if path == "" { 668 // try using jGetLoadedDynamicLibrariesInfos which is the only way to do 669 // this supported on debugserver (but only on macOS >= 12.10) 670 images, _ := p.conn.getLoadedDynamicLibraries() 671 for _, image := range images { 672 if image.MachHeader.FileType == macho.TypeExec { 673 path = image.Pathname 674 break 675 } 676 } 677 } 678 679 err = p.updateThreadList(&threadUpdater{p: p}) 680 if err != nil { 681 p.conn.conn.Close() 682 p.bi.Close() 683 return nil, err 684 } 685 p.clearThreadSignals() 686 687 if p.conn.pid <= 0 { 688 p.conn.pid, _, err = queryProcessInfo(p, 0) 689 if err != nil && !isProtocolErrorUnsupported(err) { 690 p.conn.conn.Close() 691 p.bi.Close() 692 return nil, err 693 } 694 } 695 tgt, err := proc.NewTarget(p, p.conn.pid, p.currentThread, proc.NewTargetConfig{ 696 Path: path, 697 DebugInfoDirs: debugInfoDirs, 698 DisableAsyncPreempt: runtime.GOOS == "darwin", 699 StopReason: stopReason, 700 CanDump: runtime.GOOS == "darwin"}) 701 if err != nil { 702 p.Detach(true) 703 return nil, err 704 } 705 return tgt, nil 706 } 707 708 func queryProcessInfo(p *gdbProcess, pid int) (int, string, error) { 709 pi, err := p.conn.queryProcessInfo(pid) 710 if err != nil { 711 return 0, "", err 712 } 713 if pid == 0 { 714 n, _ := strconv.ParseUint(pi["pid"], 16, 64) 715 pid = int(n) 716 } 717 return pid, pi["name"], nil 718 } 719 720 // BinInfo returns information on the binary. 721 func (p *gdbProcess) BinInfo() *proc.BinaryInfo { 722 return p.bi 723 } 724 725 // Recorded returns whether or not we are debugging 726 // a recorded "traced" program. 727 func (p *gdbProcess) Recorded() (bool, string) { 728 return p.tracedir != "", p.tracedir 729 } 730 731 // Pid returns the process ID. 732 func (p *gdbProcess) Pid() int { 733 return int(p.conn.pid) 734 } 735 736 // Valid returns true if we are not detached 737 // and the process has not exited. 738 func (p *gdbProcess) Valid() (bool, error) { 739 if p.detached { 740 return false, proc.ErrProcessDetached 741 } 742 if p.exited { 743 return false, proc.ErrProcessExited{Pid: p.Pid()} 744 } 745 if p.almostExited && p.conn.direction == proc.Forward { 746 return false, proc.ErrProcessExited{Pid: p.Pid()} 747 } 748 return true, nil 749 } 750 751 // FindThread returns the thread with the given ID. 752 func (p *gdbProcess) FindThread(threadID int) (proc.Thread, bool) { 753 thread, ok := p.threads[threadID] 754 return thread, ok 755 } 756 757 // ThreadList returns all threads in the process. 758 func (p *gdbProcess) ThreadList() []proc.Thread { 759 r := make([]proc.Thread, 0, len(p.threads)) 760 for _, thread := range p.threads { 761 r = append(r, thread) 762 } 763 return r 764 } 765 766 // Memory returns the process memory. 767 func (p *gdbProcess) Memory() proc.MemoryReadWriter { 768 return p 769 } 770 771 const ( 772 interruptSignal = 0x2 773 breakpointSignal = 0x5 774 faultSignal = 0xb 775 childSignal = 0x11 776 stopSignal = 0x13 777 778 _SIGILL = 0x4 779 _SIGFPE = 0x8 780 _SIGKILL = 0x9 781 782 debugServerTargetExcBadAccess = 0x91 783 debugServerTargetExcBadInstruction = 0x92 784 debugServerTargetExcArithmetic = 0x93 785 debugServerTargetExcEmulation = 0x94 786 debugServerTargetExcSoftware = 0x95 787 debugServerTargetExcBreakpoint = 0x96 788 ) 789 790 // ContinueOnce will continue execution of the process until 791 // a breakpoint is hit or signal is received. 792 func (p *gdbProcess) ContinueOnce(cctx *proc.ContinueOnceContext) (proc.Thread, proc.StopReason, error) { 793 if p.exited { 794 return nil, proc.StopExited, proc.ErrProcessExited{Pid: p.conn.pid} 795 } 796 if p.almostExited { 797 if p.conn.direction == proc.Forward { 798 return nil, proc.StopExited, proc.ErrProcessExited{Pid: p.conn.pid} 799 } 800 p.almostExited = false 801 } 802 803 if p.conn.direction == proc.Forward { 804 // step threads stopped at any breakpoint over their breakpoint 805 for _, thread := range p.threads { 806 if thread.CurrentBreakpoint.Breakpoint != nil { 807 if err := thread.StepInstruction(); err != nil { 808 return nil, proc.StopUnknown, err 809 } 810 } 811 } 812 } 813 814 for _, th := range p.threads { 815 th.clearBreakpointState() 816 } 817 818 p.setCtrlC(cctx, false) 819 820 // resume all threads 821 var threadID string 822 var trapthread *gdbThread 823 var tu = threadUpdater{p: p} 824 var atstart bool 825 continueLoop: 826 for { 827 tu.Reset() 828 sp, err := p.conn.resume(cctx, p.threads, &tu) 829 threadID = sp.threadID 830 if err != nil { 831 if _, exited := err.(proc.ErrProcessExited); exited { 832 p.exited = true 833 return nil, proc.StopExited, err 834 } 835 return nil, proc.StopUnknown, err 836 } 837 838 // For stubs that support qThreadStopInfo updateThreadList will 839 // find out the reason why each thread stopped. 840 // NOTE: because debugserver will sometimes send two stop packets after a 841 // continue it is important that this is the very first thing we do after 842 // resume(). See comment in threadStopInfo for an explanation. 843 p.updateThreadList(&tu) 844 845 trapthread = p.findThreadByStrID(threadID) 846 if trapthread != nil && !p.threadStopInfo { 847 // For stubs that do not support qThreadStopInfo we manually set the 848 // reason the thread returned by resume() stopped. 849 trapthread.sig = sp.sig 850 trapthread.watchAddr = sp.watchAddr 851 } 852 853 var shouldStop, shouldExitErr bool 854 trapthread, atstart, shouldStop, shouldExitErr = p.handleThreadSignals(cctx, trapthread) 855 if shouldExitErr { 856 p.almostExited = true 857 return nil, proc.StopExited, proc.ErrProcessExited{Pid: p.conn.pid} 858 } 859 if shouldStop { 860 break continueLoop 861 } 862 } 863 864 p.clearThreadRegisters() 865 866 stopReason := proc.StopUnknown 867 if atstart { 868 stopReason = proc.StopLaunched 869 } 870 871 if p.BinInfo().GOOS == "linux" { 872 if err := linutil.ElfUpdateSharedObjects(p); err != nil { 873 return nil, stopReason, err 874 } 875 } 876 877 if err := p.setCurrentBreakpoints(); err != nil { 878 return nil, stopReason, err 879 } 880 881 if trapthread == nil { 882 return nil, stopReason, fmt.Errorf("could not find thread %s", threadID) 883 } 884 885 err := machTargetExcToError(trapthread.sig) 886 if err != nil { 887 // the signals that are reported here can not be propagated back to the target process. 888 trapthread.sig = 0 889 } 890 p.currentThread = trapthread 891 return trapthread, stopReason, err 892 } 893 894 func (p *gdbProcess) findThreadByStrID(threadID string) *gdbThread { 895 for _, thread := range p.threads { 896 if thread.strID == threadID { 897 return thread 898 } 899 } 900 return nil 901 } 902 903 // handleThreadSignals looks at the signals received by each thread and 904 // decides which ones to mask and which ones to propagate back to the target 905 // and returns true if we should stop execution in response to one of the 906 // signals and return control to the user. 907 // Adjusts trapthread to a thread that we actually want to stop at. 908 func (p *gdbProcess) handleThreadSignals(cctx *proc.ContinueOnceContext, trapthread *gdbThread) (trapthreadOut *gdbThread, atstart, shouldStop, shouldExitErr bool) { 909 var trapthreadCandidate *gdbThread 910 911 for _, th := range p.threads { 912 isStopSignal := false 913 914 // 0x5 is always a breakpoint, a manual stop either manifests as 0x13 915 // (lldb), 0x11 (debugserver) or 0x2 (gdbserver). 916 // Since 0x2 could also be produced by the user 917 // pressing ^C (in which case it should be passed to the inferior) we need 918 // the ctrlC flag to know that we are the originators. 919 switch th.sig { 920 case interruptSignal: // interrupt 921 if p.getCtrlC(cctx) { 922 isStopSignal = true 923 } 924 case breakpointSignal: // breakpoint 925 isStopSignal = true 926 case childSignal: // stop on debugserver but SIGCHLD on lldb-server/linux 927 if p.conn.isDebugserver { 928 isStopSignal = true 929 } 930 case stopSignal: // stop 931 isStopSignal = true 932 933 case _SIGKILL: 934 if p.tracedir != "" { 935 // RR will send a synthetic SIGKILL packet right before the program 936 // exits, even if the program exited normally. 937 // Treat this signal as if the process had exited because right after 938 // this it is still possible to set breakpoints and rewind the process. 939 shouldExitErr = true 940 isStopSignal = true 941 } 942 943 // The following are fake BSD-style signals sent by debugserver 944 // Unfortunately debugserver can not convert them into signals for the 945 // process so we must stop here. 946 case debugServerTargetExcBadAccess, debugServerTargetExcBadInstruction, debugServerTargetExcArithmetic, debugServerTargetExcEmulation, debugServerTargetExcSoftware, debugServerTargetExcBreakpoint: 947 948 trapthreadCandidate = th 949 shouldStop = true 950 951 // Signal 0 is returned by rr when it reaches the start of the process 952 // in backward continue mode. 953 case 0: 954 if p.conn.direction == proc.Backward && th == trapthread { 955 isStopSignal = true 956 atstart = true 957 } 958 959 default: 960 // any other signal is always propagated to inferior 961 } 962 963 if isStopSignal { 964 if trapthreadCandidate == nil { 965 trapthreadCandidate = th 966 } 967 th.sig = 0 968 shouldStop = true 969 } 970 } 971 972 if (trapthread == nil || trapthread.sig != 0) && trapthreadCandidate != nil { 973 // proc.Continue wants us to return one of the threads that we should stop 974 // at, if the thread returned by vCont received a signal that we want to 975 // propagate back to the target thread but there were also other threads 976 // that we wish to stop at we should pick one of those. 977 trapthread = trapthreadCandidate 978 } 979 980 if p.getCtrlC(cctx) || cctx.GetManualStopRequested() { 981 // If we request an interrupt and a target thread simultaneously receives 982 // an unrelated singal debugserver will discard our interrupt request and 983 // report the signal but we should stop anyway. 984 shouldStop = true 985 } 986 987 return trapthread, atstart, shouldStop, shouldExitErr 988 } 989 990 // RequestManualStop will attempt to stop the process 991 // without a breakpoint or signal having been received. 992 func (p *gdbProcess) RequestManualStop(cctx *proc.ContinueOnceContext) error { 993 if !p.conn.running { 994 return nil 995 } 996 p.ctrlC = true 997 return p.conn.sendCtrlC() 998 } 999 1000 func (p *gdbProcess) setCtrlC(cctx *proc.ContinueOnceContext, v bool) { 1001 cctx.StopMu.Lock() 1002 p.ctrlC = v 1003 cctx.StopMu.Unlock() 1004 } 1005 1006 func (p *gdbProcess) getCtrlC(cctx *proc.ContinueOnceContext) bool { 1007 cctx.StopMu.Lock() 1008 defer cctx.StopMu.Unlock() 1009 return p.ctrlC 1010 } 1011 1012 // Detach will detach from the target process, 1013 // if 'kill' is true it will also kill the process. 1014 func (p *gdbProcess) Detach(kill bool) error { 1015 if kill && !p.exited { 1016 err := p.conn.kill() 1017 if err != nil { 1018 if _, exited := err.(proc.ErrProcessExited); !exited { 1019 return err 1020 } 1021 p.exited = true 1022 } 1023 } 1024 if !p.exited { 1025 if err := p.conn.detach(); err != nil { 1026 return err 1027 } 1028 } 1029 if p.process != nil { 1030 p.process.Kill() 1031 <-p.waitChan 1032 p.process = nil 1033 } 1034 p.detached = true 1035 if p.onDetach != nil { 1036 p.onDetach() 1037 } 1038 return p.bi.Close() 1039 } 1040 1041 // Restart will restart the process from the given position. 1042 func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.Thread, error) { 1043 if p.tracedir == "" { 1044 return nil, proc.ErrNotRecorded 1045 } 1046 1047 // Is this a checkpoint on a server using local checkpoints? 1048 if len(pos) > 1 && pos[:1] == "c" && p.conn.isUndoServer { 1049 cpid, _ := strconv.Atoi(pos[1:]) 1050 checkpoint, exists := p.localCheckpoints[cpid] 1051 if !exists { 1052 return nil, errors.New("Checkpoint not found") 1053 } 1054 pos = checkpoint.When 1055 } 1056 1057 p.exited = false 1058 p.almostExited = false 1059 1060 for _, th := range p.threads { 1061 th.clearBreakpointState() 1062 } 1063 1064 p.ctrlC = false 1065 1066 err := p.conn.restart(pos) 1067 if err != nil { 1068 return nil, err 1069 } 1070 1071 // for some reason we have to send a vCont;c after a vRun to make rr behave 1072 // properly, because that's what gdb does. 1073 if !p.conn.isUndoServer { 1074 _, err = p.conn.resume(cctx, nil, nil) 1075 if err != nil { 1076 return nil, err 1077 } 1078 } 1079 1080 err = p.updateThreadList(&threadUpdater{p: p}) 1081 if err != nil { 1082 return nil, err 1083 } 1084 p.clearThreadSignals() 1085 p.clearThreadRegisters() 1086 1087 for _, bp := range p.breakpoints.M { 1088 p.WriteBreakpoint(bp) 1089 } 1090 1091 return p.currentThread, p.setCurrentBreakpoints() 1092 } 1093 1094 // When executes the 'when' command for the Mozilla RR/Undo backends. 1095 // This command will return rr's internal event number. 1096 func (p *gdbProcess) When() (string, error) { 1097 if p.tracedir == "" { 1098 return "", proc.ErrNotRecorded 1099 } 1100 result := "" 1101 if p.conn.isUndoServer { 1102 extent, err := p.conn.undoCmd("get_time") 1103 if err != nil { 1104 return "", err 1105 } 1106 result = extent 1107 } else { 1108 event, err := p.conn.qRRCmd("when") 1109 if err != nil { 1110 return "", err 1111 } 1112 result = strings.TrimSpace(event) 1113 } 1114 return result, nil 1115 } 1116 1117 const ( 1118 checkpointPrefix = "Checkpoint " 1119 ) 1120 1121 // Checkpoint creates a checkpoint from which you can restart the program. 1122 func (p *gdbProcess) Checkpoint(where string) (int, error) { 1123 if p.tracedir == "" { 1124 return -1, proc.ErrNotRecorded 1125 } 1126 1127 // Handle locally managed checkpoints first 1128 if p.conn.isUndoServer { 1129 cpid := p.localCheckpointLastId 1130 p.localCheckpointLastId++ 1131 when, err := p.conn.undoCmd("get_time") 1132 if err != nil { 1133 return -1, err 1134 } 1135 p.localCheckpoints[cpid] = proc.Checkpoint{ID: cpid, When: when, Where: where} 1136 return cpid, nil 1137 } 1138 1139 resp, err := p.conn.qRRCmd("checkpoint", where) 1140 if err != nil { 1141 return -1, err 1142 } 1143 1144 if !strings.HasPrefix(resp, checkpointPrefix) { 1145 return -1, fmt.Errorf("can not parse checkpoint response %q", resp) 1146 } 1147 1148 idstr := resp[len(checkpointPrefix):] 1149 space := strings.Index(idstr, " ") 1150 if space < 0 { 1151 return -1, fmt.Errorf("can not parse checkpoint response %q", resp) 1152 } 1153 idstr = idstr[:space] 1154 1155 cpid, err := strconv.Atoi(idstr) 1156 if err != nil { 1157 return -1, err 1158 } 1159 return cpid, nil 1160 } 1161 1162 // Checkpoints returns a list of all checkpoints set. 1163 func (p *gdbProcess) Checkpoints() ([]proc.Checkpoint, error) { 1164 if p.tracedir == "" { 1165 return nil, proc.ErrNotRecorded 1166 } 1167 1168 // Handle locally managed checkpoints first 1169 if p.conn.isUndoServer { 1170 r := make([]proc.Checkpoint, 0, len(p.localCheckpoints)) 1171 for _, cp := range p.localCheckpoints { 1172 r = append(r, cp) 1173 } 1174 return r, nil 1175 } 1176 1177 resp, err := p.conn.qRRCmd("info checkpoints") 1178 if err != nil { 1179 return nil, err 1180 } 1181 lines := strings.Split(resp, "\n") 1182 r := make([]proc.Checkpoint, 0, len(lines)-1) 1183 for _, line := range lines[1:] { 1184 if line == "" { 1185 continue 1186 } 1187 fields := strings.Split(line, "\t") 1188 if len(fields) != 3 { 1189 return nil, fmt.Errorf("can not parse \"info checkpoints\" output line %q", line) 1190 } 1191 cpid, err := strconv.Atoi(fields[0]) 1192 if err != nil { 1193 return nil, fmt.Errorf("can not parse \"info checkpoints\" output line %q: %v", line, err) 1194 } 1195 r = append(r, proc.Checkpoint{ID: cpid, When: fields[1], Where: fields[2]}) 1196 } 1197 return r, nil 1198 } 1199 1200 const deleteCheckpointPrefix = "Deleted checkpoint " 1201 1202 // ClearCheckpoint clears the checkpoint for the given ID. 1203 func (p *gdbProcess) ClearCheckpoint(id int) error { 1204 if p.tracedir == "" { 1205 return proc.ErrNotRecorded 1206 } 1207 1208 // Handle locally managed checkpoints first 1209 if p.conn.isUndoServer { 1210 delete(p.localCheckpoints, id) 1211 // We don't care if it didn't exist 1212 return nil 1213 } 1214 1215 resp, err := p.conn.qRRCmd("delete checkpoint", strconv.Itoa(id)) 1216 if err != nil { 1217 return err 1218 } 1219 if !strings.HasPrefix(resp, deleteCheckpointPrefix) { 1220 return errors.New(resp) 1221 } 1222 return nil 1223 } 1224 1225 // ChangeDirection sets whether to run the program forwards or in reverse execution. 1226 func (p *gdbProcess) ChangeDirection(dir proc.Direction) error { 1227 if p.tracedir == "" { 1228 if dir != proc.Forward { 1229 return proc.ErrNotRecorded 1230 } 1231 return nil 1232 } 1233 if p.conn.conn == nil { 1234 return proc.ErrProcessExited{Pid: p.conn.pid} 1235 } 1236 if p.conn.direction == dir { 1237 return nil 1238 } 1239 if p.Breakpoints().HasSteppingBreakpoints() { 1240 return ErrDirChange 1241 } 1242 p.conn.direction = dir 1243 return nil 1244 } 1245 1246 // StartCallInjection notifies the backend that we are about to inject a function call. 1247 func (p *gdbProcess) StartCallInjection() (func(), error) { 1248 if p.tracedir == "" { 1249 return func() {}, nil 1250 } 1251 if p.conn.conn == nil { 1252 return nil, proc.ErrProcessExited{Pid: p.conn.pid} 1253 } 1254 if p.conn.direction != proc.Forward { 1255 return nil, ErrStartCallInjectionBackwards 1256 } 1257 1258 if p.conn.isUndoServer { 1259 _, err := p.conn.undoCmd("set_debuggee_volatile", "1") 1260 if err != nil { 1261 return nil, err 1262 } 1263 return func() { 1264 _, _ = p.conn.undoCmd("set_debuggee_volatile", "0") 1265 }, nil 1266 } 1267 1268 // Normally it's impossible to inject function calls in a recorded target 1269 // because the sequence of instructions that the target will execute is 1270 // predetermined. 1271 // RR however allows this in a "diversion". When a diversion is started rr 1272 // takes the current state of the process and runs it forward as a normal 1273 // process, not following the recording. 1274 // The gdb serial protocol does not have a way to start a diversion and gdb 1275 // (the main frontend of rr) does not know how to do it. Instead a 1276 // diversion is started by reading siginfo, because that's the first 1277 // request gdb does when starting a function call injection. 1278 1279 _, err := p.conn.qXfer("siginfo", "", true) 1280 if err != nil { 1281 return nil, err 1282 } 1283 1284 return func() { 1285 _ = p.conn.qXferWrite("siginfo", "") // rr always returns an error for qXfer:siginfo:write... even though it works 1286 }, nil 1287 } 1288 1289 // GetDirection returns the current direction of execution. 1290 func (p *gdbProcess) GetDirection() proc.Direction { 1291 return p.conn.direction 1292 } 1293 1294 // Breakpoints returns the list of breakpoints currently set. 1295 func (p *gdbProcess) Breakpoints() *proc.BreakpointMap { 1296 return &p.breakpoints 1297 } 1298 1299 // FindBreakpoint returns the breakpoint at the given address. 1300 func (p *gdbProcess) FindBreakpoint(pc uint64) (*proc.Breakpoint, bool) { 1301 // Directly use addr to lookup breakpoint. 1302 if bp, ok := p.breakpoints.M[pc]; ok { 1303 return bp, true 1304 } 1305 return nil, false 1306 } 1307 1308 func watchTypeToBreakpointType(wtype proc.WatchType) breakpointType { 1309 switch { 1310 case wtype.Read() && wtype.Write(): 1311 return accessWatchpoint 1312 case wtype.Write(): 1313 return writeWatchpoint 1314 case wtype.Read(): 1315 return readWatchpoint 1316 default: 1317 return swBreakpoint 1318 } 1319 } 1320 1321 func (p *gdbProcess) WriteBreakpoint(bp *proc.Breakpoint) error { 1322 kind := p.breakpointKind 1323 if bp.WatchType != 0 { 1324 kind = bp.WatchType.Size() 1325 } 1326 return p.conn.setBreakpoint(bp.Addr, watchTypeToBreakpointType(bp.WatchType), kind) 1327 } 1328 1329 func (p *gdbProcess) EraseBreakpoint(bp *proc.Breakpoint) error { 1330 kind := p.breakpointKind 1331 if bp.WatchType != 0 { 1332 kind = bp.WatchType.Size() 1333 } 1334 return p.conn.clearBreakpoint(bp.Addr, watchTypeToBreakpointType(bp.WatchType), kind) 1335 } 1336 1337 type threadUpdater struct { 1338 p *gdbProcess 1339 seen map[int]bool 1340 done bool 1341 } 1342 1343 func (tu *threadUpdater) Reset() { 1344 tu.done = false 1345 tu.seen = nil 1346 } 1347 1348 func (tu *threadUpdater) Add(threads []string) error { 1349 if tu.done { 1350 panic("threadUpdater: Add after Finish") 1351 } 1352 if tu.seen == nil { 1353 tu.seen = map[int]bool{} 1354 } 1355 for _, threadID := range threads { 1356 b := threadID 1357 if period := strings.Index(b, "."); period >= 0 { 1358 b = b[period+1:] 1359 } 1360 n, err := strconv.ParseUint(b, 16, 32) 1361 if err != nil { 1362 return &GdbMalformedThreadIDError{threadID} 1363 } 1364 tid := int(n) 1365 tu.seen[tid] = true 1366 if _, found := tu.p.threads[tid]; !found { 1367 tu.p.threads[tid] = &gdbThread{ID: tid, strID: threadID, p: tu.p} 1368 } 1369 } 1370 return nil 1371 } 1372 1373 func (tu *threadUpdater) Finish() { 1374 tu.done = true 1375 for threadID := range tu.p.threads { 1376 _, threadSeen := tu.seen[threadID] 1377 if threadSeen { 1378 continue 1379 } 1380 delete(tu.p.threads, threadID) 1381 if tu.p.currentThread != nil && tu.p.currentThread.ID == threadID { 1382 tu.p.currentThread = nil 1383 } 1384 } 1385 if tu.p.currentThread != nil { 1386 if _, exists := tu.p.threads[tu.p.currentThread.ID]; !exists { 1387 // current thread was removed 1388 tu.p.currentThread = nil 1389 } 1390 } 1391 if tu.p.currentThread == nil { 1392 for _, thread := range tu.p.threads { 1393 tu.p.currentThread = thread 1394 break 1395 } 1396 } 1397 } 1398 1399 // updateThreadList retrieves the list of inferior threads from 1400 // the stub and passes it to threadUpdater. 1401 // Some stubs will return the list of running threads in the stop packet, if 1402 // this happens the threadUpdater will know that we have already updated the 1403 // thread list and the first step of updateThreadList will be skipped. 1404 func (p *gdbProcess) updateThreadList(tu *threadUpdater) error { 1405 if !tu.done { 1406 first := true 1407 for { 1408 threads, err := p.conn.queryThreads(first) 1409 if err != nil { 1410 return err 1411 } 1412 if len(threads) == 0 { 1413 break 1414 } 1415 first = false 1416 if err := tu.Add(threads); err != nil { 1417 return err 1418 } 1419 } 1420 1421 tu.Finish() 1422 } 1423 1424 for _, th := range p.threads { 1425 if p.threadStopInfo { 1426 sp, err := p.conn.threadStopInfo(th.strID) 1427 if err != nil { 1428 if isProtocolErrorUnsupported(err) { 1429 p.threadStopInfo = false 1430 break 1431 } 1432 return err 1433 } 1434 th.setbp = (sp.reason == "breakpoint" || (sp.reason == "" && sp.sig == breakpointSignal) || (sp.watchAddr > 0)) 1435 th.sig = sp.sig 1436 th.watchAddr = sp.watchAddr 1437 } else { 1438 th.sig = 0 1439 th.watchAddr = 0 1440 } 1441 } 1442 1443 return nil 1444 } 1445 1446 // clearThreadRegisters clears the memoized thread register state. 1447 func (p *gdbProcess) clearThreadRegisters() { 1448 for _, thread := range p.threads { 1449 thread.regs.regs = nil 1450 } 1451 } 1452 1453 func (p *gdbProcess) clearThreadSignals() { 1454 for _, th := range p.threads { 1455 th.sig = 0 1456 } 1457 } 1458 1459 func (p *gdbProcess) setCurrentBreakpoints() error { 1460 if p.threadStopInfo { 1461 for _, th := range p.threads { 1462 if th.setbp { 1463 err := th.SetCurrentBreakpoint(true) 1464 if err != nil { 1465 return err 1466 } 1467 } 1468 } 1469 } 1470 if !p.threadStopInfo { 1471 for _, th := range p.threads { 1472 if th.CurrentBreakpoint.Breakpoint == nil { 1473 err := th.SetCurrentBreakpoint(true) 1474 if err != nil { 1475 return err 1476 } 1477 } 1478 } 1479 } 1480 return nil 1481 } 1482 1483 // ReadMemory will read into 'data' memory at the address provided. 1484 func (p *gdbProcess) ReadMemory(data []byte, addr uint64) (n int, err error) { 1485 err = p.conn.readMemory(data, addr) 1486 if err != nil { 1487 return 0, err 1488 } 1489 return len(data), nil 1490 } 1491 1492 // WriteMemory will write into the memory at 'addr' the data provided. 1493 func (p *gdbProcess) WriteMemory(addr uint64, data []byte) (written int, err error) { 1494 return p.conn.writeMemory(addr, data) 1495 } 1496 1497 func (t *gdbThread) ProcessMemory() proc.MemoryReadWriter { 1498 return t.p 1499 } 1500 1501 // Location returns the current location of this thread. 1502 func (t *gdbThread) Location() (*proc.Location, error) { 1503 regs, err := t.Registers() 1504 if err != nil { 1505 return nil, err 1506 } 1507 if pcreg, ok := regs.(*gdbRegisters).regs[regs.(*gdbRegisters).regnames.PC]; !ok { 1508 t.p.conn.log.Errorf("thread %d could not find RIP register", t.ID) 1509 } else if len(pcreg.value) < t.p.bi.Arch.PtrSize() { 1510 t.p.conn.log.Errorf("thread %d bad length for RIP register: %d", t.ID, len(pcreg.value)) 1511 } 1512 pc := regs.PC() 1513 f, l, fn := t.p.bi.PCToLine(pc) 1514 return &proc.Location{PC: pc, File: f, Line: l, Fn: fn}, nil 1515 } 1516 1517 // Breakpoint returns the current active breakpoint for this thread. 1518 func (t *gdbThread) Breakpoint() *proc.BreakpointState { 1519 return &t.CurrentBreakpoint 1520 } 1521 1522 // ThreadID returns this threads ID. 1523 func (t *gdbThread) ThreadID() int { 1524 return t.ID 1525 } 1526 1527 // Registers returns the CPU registers for this thread. 1528 func (t *gdbThread) Registers() (proc.Registers, error) { 1529 if t.regs.regs == nil { 1530 if err := t.reloadRegisters(); err != nil { 1531 return nil, err 1532 } 1533 } 1534 return &t.regs, nil 1535 } 1536 1537 // RestoreRegisters will set the CPU registers the value of those provided. 1538 func (t *gdbThread) RestoreRegisters(savedRegs proc.Registers) error { 1539 copy(t.regs.buf, savedRegs.(*gdbRegisters).buf) 1540 return t.writeRegisters() 1541 } 1542 1543 // BinInfo will return information on the binary being debugged. 1544 func (t *gdbThread) BinInfo() *proc.BinaryInfo { 1545 return t.p.bi 1546 } 1547 1548 // Common returns common information across Process implementations. 1549 func (t *gdbThread) Common() *proc.CommonThread { 1550 return &t.common 1551 } 1552 1553 // StepInstruction will step exactly 1 CPU instruction. 1554 func (t *gdbThread) StepInstruction() error { 1555 pc := t.regs.PC() 1556 if bp, atbp := t.p.breakpoints.M[pc]; atbp && bp.WatchType == 0 { 1557 err := t.p.conn.clearBreakpoint(pc, swBreakpoint, t.p.breakpointKind) 1558 if err != nil { 1559 return err 1560 } 1561 defer t.p.conn.setBreakpoint(pc, swBreakpoint, t.p.breakpointKind) 1562 } 1563 // Reset thread registers so the next call to 1564 // Thread.Registers will not be cached. 1565 t.regs.regs = nil 1566 return t.p.conn.step(t, &threadUpdater{p: t.p}, false) 1567 } 1568 1569 // SoftExc returns true if this thread received a software exception during the last resume. 1570 func (t *gdbThread) SoftExc() bool { 1571 return t.setbp 1572 } 1573 1574 // Blocked returns true if the thread is blocked in runtime or kernel code. 1575 func (t *gdbThread) Blocked() bool { 1576 regs, err := t.Registers() 1577 if err != nil { 1578 return false 1579 } 1580 pc := regs.PC() 1581 f, ln, fn := t.BinInfo().PCToLine(pc) 1582 if fn == nil { 1583 if f == "" && ln == 0 { 1584 return true 1585 } 1586 return false 1587 } 1588 switch fn.Name { 1589 case "runtime.futex", "runtime.usleep", "runtime.clone": 1590 return true 1591 case "runtime.kevent": 1592 return true 1593 case "runtime.mach_semaphore_wait", "runtime.mach_semaphore_timedwait": 1594 return true 1595 default: 1596 return strings.HasPrefix(fn.Name, "syscall.Syscall") || strings.HasPrefix(fn.Name, "syscall.RawSyscall") 1597 } 1598 } 1599 1600 func (p *gdbProcess) MemoryMap() ([]proc.MemoryMapEntry, error) { 1601 r := []proc.MemoryMapEntry{} 1602 addr := uint64(0) 1603 for addr != ^uint64(0) { 1604 mri, err := p.conn.memoryRegionInfo(addr) 1605 if err != nil { 1606 return nil, err 1607 } 1608 if addr+mri.size <= addr { 1609 return nil, errors.New("qMemoryRegionInfo response wrapped around the address space or stuck") 1610 } 1611 if mri.permissions != "" { 1612 var mme proc.MemoryMapEntry 1613 1614 mme.Addr = addr 1615 mme.Size = mri.size 1616 mme.Read = strings.Contains(mri.permissions, "r") 1617 mme.Write = strings.Contains(mri.permissions, "w") 1618 mme.Exec = strings.Contains(mri.permissions, "x") 1619 1620 r = append(r, mme) 1621 } 1622 addr += mri.size 1623 } 1624 return r, nil 1625 } 1626 1627 func (p *gdbProcess) DumpProcessNotes(notes []elfwriter.Note, threadDone func()) (threadsDone bool, out []elfwriter.Note, err error) { 1628 return false, notes, nil 1629 } 1630 1631 func (regs *gdbRegisters) init(regsInfo []gdbRegisterInfo, arch *proc.Arch, regnames *gdbRegnames) { 1632 regs.arch = arch 1633 regs.regnames = regnames 1634 regs.regs = make(map[string]gdbRegister) 1635 regs.regsInfo = regsInfo 1636 1637 regsz := 0 1638 for _, reginfo := range regsInfo { 1639 if endoff := reginfo.Offset + (reginfo.Bitsize / 8); endoff > regsz { 1640 regsz = endoff 1641 } 1642 } 1643 regs.buf = make([]byte, regsz) 1644 for _, reginfo := range regsInfo { 1645 regs.regs[reginfo.Name] = regs.gdbRegisterNew(®info) 1646 } 1647 } 1648 1649 func (regs *gdbRegisters) gdbRegisterNew(reginfo *gdbRegisterInfo) gdbRegister { 1650 return gdbRegister{regnum: reginfo.Regnum, value: regs.buf[reginfo.Offset : reginfo.Offset+reginfo.Bitsize/8], ignoreOnWrite: reginfo.ignoreOnWrite} 1651 } 1652 1653 // reloadRegisters loads the current value of the thread's registers. 1654 // It will also load the address of the thread's G. 1655 // Loading the address of G can be done in one of two ways reloadGAlloc, if 1656 // the stub can allocate memory, or reloadGAtPC, if the stub can't. 1657 func (t *gdbThread) reloadRegisters() error { 1658 if t.regs.regs == nil { 1659 t.regs.init(t.p.conn.regsInfo, t.p.bi.Arch, t.p.regnames) 1660 } 1661 1662 if t.p.gcmdok { 1663 if err := t.p.conn.readRegisters(t.strID, t.regs.buf); err != nil { 1664 gdberr, isProt := err.(*GdbProtocolError) 1665 if isProtocolErrorUnsupported(err) || (t.p.conn.isDebugserver && isProt && gdberr.code == "E74") { 1666 t.p.gcmdok = false 1667 } else { 1668 return err 1669 } 1670 } 1671 } 1672 if !t.p.gcmdok { 1673 for _, reginfo := range t.p.conn.regsInfo { 1674 if err := t.p.conn.readRegister(t.strID, reginfo.Regnum, t.regs.regs[reginfo.Name].value); err != nil { 1675 return err 1676 } 1677 } 1678 } 1679 1680 if t.p.bi.Arch.Name == "arm64" { 1681 // no need to play around with the GInstr on ARM64 because 1682 // the G addr is stored in a register 1683 1684 t.regs.gaddr = t.regs.byName("x28") 1685 t.regs.hasgaddr = true 1686 t.regs.tls = 0 1687 } else { 1688 return t.readG() 1689 } 1690 1691 return nil 1692 } 1693 1694 func (t *gdbThread) writeSomeRegisters(regNames ...string) error { 1695 if t.p.gcmdok { 1696 return t.p.conn.writeRegisters(t.strID, t.regs.buf) 1697 } 1698 for _, regName := range regNames { 1699 if err := t.p.conn.writeRegister(t.strID, t.regs.regs[regName].regnum, t.regs.regs[regName].value); err != nil { 1700 return err 1701 } 1702 } 1703 return nil 1704 } 1705 1706 func (t *gdbThread) writeRegisters() error { 1707 if t.p.gcmdok && t.p._Gcmdok { 1708 err := t.p.conn.writeRegisters(t.strID, t.regs.buf) 1709 if isProtocolErrorUnsupported(err) { 1710 t.p._Gcmdok = false 1711 } else { 1712 return err 1713 } 1714 1715 } 1716 for _, r := range t.regs.regs { 1717 if r.ignoreOnWrite { 1718 continue 1719 } 1720 if err := t.p.conn.writeRegister(t.strID, r.regnum, r.value); err != nil { 1721 return err 1722 } 1723 } 1724 return nil 1725 } 1726 1727 func (t *gdbThread) readSomeRegisters(regNames ...string) error { 1728 if t.p.gcmdok { 1729 return t.p.conn.readRegisters(t.strID, t.regs.buf) 1730 } 1731 for _, regName := range regNames { 1732 err := t.p.conn.readRegister(t.strID, t.regs.regs[regName].regnum, t.regs.regs[regName].value) 1733 if err != nil { 1734 return err 1735 } 1736 } 1737 return nil 1738 } 1739 1740 func (t *gdbThread) clearBreakpointState() { 1741 t.setbp = false 1742 t.CurrentBreakpoint.Clear() 1743 } 1744 1745 // SetCurrentBreakpoint will find and set the threads current breakpoint. 1746 func (t *gdbThread) SetCurrentBreakpoint(adjustPC bool) error { 1747 // adjustPC is ignored, it is the stub's responsibiility to set the PC 1748 // address correctly after hitting a breakpoint. 1749 t.CurrentBreakpoint.Clear() 1750 if t.watchAddr > 0 { 1751 t.CurrentBreakpoint.Breakpoint = t.p.Breakpoints().M[t.watchAddr] 1752 if t.CurrentBreakpoint.Breakpoint == nil { 1753 return fmt.Errorf("could not find watchpoint at address %#x", t.watchAddr) 1754 } 1755 return nil 1756 } 1757 regs, err := t.Registers() 1758 if err != nil { 1759 return err 1760 } 1761 pc := regs.PC() 1762 if bp, ok := t.p.FindBreakpoint(pc); ok { 1763 if t.regs.PC() != bp.Addr { 1764 if err := t.setPC(bp.Addr); err != nil { 1765 return err 1766 } 1767 } 1768 t.CurrentBreakpoint.Breakpoint = bp 1769 } 1770 return nil 1771 } 1772 1773 func (regs *gdbRegisters) PC() uint64 { 1774 return binary.LittleEndian.Uint64(regs.regs[regs.regnames.PC].value) 1775 } 1776 1777 func (regs *gdbRegisters) setPC(value uint64) { 1778 binary.LittleEndian.PutUint64(regs.regs[regs.regnames.PC].value, value) 1779 } 1780 1781 func (regs *gdbRegisters) SP() uint64 { 1782 return binary.LittleEndian.Uint64(regs.regs[regs.regnames.SP].value) 1783 } 1784 1785 func (regs *gdbRegisters) BP() uint64 { 1786 return binary.LittleEndian.Uint64(regs.regs[regs.regnames.BP].value) 1787 } 1788 1789 func (regs *gdbRegisters) CX() uint64 { 1790 return binary.LittleEndian.Uint64(regs.regs[regs.regnames.CX].value) 1791 } 1792 1793 func (regs *gdbRegisters) setCX(value uint64) { 1794 binary.LittleEndian.PutUint64(regs.regs[regs.regnames.CX].value, value) 1795 } 1796 1797 func (regs *gdbRegisters) TLS() uint64 { 1798 return regs.tls 1799 } 1800 1801 func (regs *gdbRegisters) GAddr() (uint64, bool) { 1802 return regs.gaddr, regs.hasgaddr 1803 } 1804 1805 func (regs *gdbRegisters) LR() uint64 { 1806 return binary.LittleEndian.Uint64(regs.regs["lr"].value) 1807 } 1808 1809 func (regs *gdbRegisters) byName(name string) uint64 { 1810 reg, ok := regs.regs[name] 1811 if !ok { 1812 return 0 1813 } 1814 return binary.LittleEndian.Uint64(reg.value) 1815 } 1816 1817 func (r *gdbRegisters) FloatLoadError() error { 1818 return nil 1819 } 1820 1821 // SetPC will set the value of the PC register to the given value. 1822 func (t *gdbThread) setPC(pc uint64) error { 1823 _, _ = t.Registers() // Registes must be loaded first 1824 t.regs.setPC(pc) 1825 if t.p.gcmdok { 1826 return t.p.conn.writeRegisters(t.strID, t.regs.buf) 1827 } 1828 reg := t.regs.regs[t.regs.regnames.PC] 1829 return t.p.conn.writeRegister(t.strID, reg.regnum, reg.value) 1830 } 1831 1832 // SetReg will change the value of a list of registers 1833 func (t *gdbThread) SetReg(regNum uint64, reg *op.DwarfRegister) error { 1834 regName := registerName(t.p.bi.Arch, regNum) 1835 _, _ = t.Registers() // Registers must be loaded first 1836 gdbreg, ok := t.regs.regs[regName] 1837 if !ok && strings.HasPrefix(regName, "xmm") { 1838 // XMMn and YMMn are the same amd64 register (in different sizes), if we 1839 // don't find XMMn try YMMn or ZMMn instead. 1840 gdbreg, ok = t.regs.regs["y"+regName[1:]] 1841 if !ok { 1842 gdbreg, ok = t.regs.regs["z"+regName[1:]] 1843 } 1844 } 1845 if !ok && t.p.bi.Arch.Name == "arm64" && regName == "x30" { 1846 gdbreg, ok = t.regs.regs["lr"] 1847 } 1848 if !ok && regName == "rflags" { 1849 // rr has eflags instead of rflags 1850 regName = "eflags" 1851 gdbreg, ok = t.regs.regs[regName] 1852 if ok { 1853 reg.FillBytes() 1854 reg.Bytes = reg.Bytes[:4] 1855 } 1856 } 1857 if !ok { 1858 return fmt.Errorf("could not set register %s: not found", regName) 1859 } 1860 reg.FillBytes() 1861 1862 wrongSizeErr := func(n int) error { 1863 return fmt.Errorf("could not set register %s: wrong size, expected %d got %d", regName, n, len(reg.Bytes)) 1864 } 1865 1866 if len(reg.Bytes) == len(gdbreg.value) { 1867 copy(gdbreg.value, reg.Bytes) 1868 err := t.p.conn.writeRegister(t.strID, gdbreg.regnum, gdbreg.value) 1869 if err != nil { 1870 return err 1871 } 1872 if t.p.conn.workaroundReg != nil && len(gdbreg.value) > 16 { 1873 // This is a workaround for a bug in debugserver where register writes (P 1874 // packet) on AVX-2 and AVX-512 registers are ignored unless they are 1875 // followed by a write to an AVX register. 1876 // See: 1877 // Issue #2767 1878 // https://bugs.llvm.org/show_bug.cgi?id=52362 1879 reg := t.regs.gdbRegisterNew(t.p.conn.workaroundReg) 1880 return t.p.conn.writeRegister(t.strID, reg.regnum, reg.value) 1881 } 1882 } else if len(reg.Bytes) == 2*len(gdbreg.value) && strings.HasPrefix(regName, "xmm") { 1883 // rr uses xmmN for the low part of the register and ymmNh for the high part 1884 gdbregh, ok := t.regs.regs["y"+regName[1:]+"h"] 1885 if !ok { 1886 return wrongSizeErr(len(gdbreg.value)) 1887 } 1888 if len(reg.Bytes) != len(gdbreg.value)+len(gdbregh.value) { 1889 return wrongSizeErr(len(gdbreg.value) + len(gdbregh.value)) 1890 } 1891 copy(gdbreg.value, reg.Bytes[:len(gdbreg.value)]) 1892 copy(gdbregh.value, reg.Bytes[len(gdbreg.value):]) 1893 err := t.p.conn.writeRegister(t.strID, gdbreg.regnum, gdbreg.value) 1894 if err != nil { 1895 return err 1896 } 1897 err = t.p.conn.writeRegister(t.strID, gdbregh.regnum, gdbregh.value) 1898 if err != nil { 1899 return err 1900 } 1901 } else { 1902 return wrongSizeErr(len(gdbreg.value)) 1903 } 1904 return nil 1905 } 1906 1907 func (regs *gdbRegisters) Slice(floatingPoint bool) ([]proc.Register, error) { 1908 r := make([]proc.Register, 0, len(regs.regsInfo)) 1909 for _, reginfo := range regs.regsInfo { 1910 if reginfo.Group == "float" && !floatingPoint { 1911 continue 1912 } 1913 switch { 1914 case reginfo.Name == "eflags": 1915 r = proc.AppendBytesRegister(r, "Rflags", regs.regs[reginfo.Name].value) 1916 case reginfo.Name == "mxcsr": 1917 r = proc.AppendBytesRegister(r, reginfo.Name, regs.regs[reginfo.Name].value) 1918 case reginfo.Bitsize == 16: 1919 r = proc.AppendBytesRegister(r, reginfo.Name, regs.regs[reginfo.Name].value) 1920 case reginfo.Bitsize == 32: 1921 r = proc.AppendBytesRegister(r, reginfo.Name, regs.regs[reginfo.Name].value) 1922 case reginfo.Bitsize == 64: 1923 r = proc.AppendBytesRegister(r, reginfo.Name, regs.regs[reginfo.Name].value) 1924 case reginfo.Bitsize == 80: 1925 if !floatingPoint { 1926 continue 1927 } 1928 idx := 0 1929 for _, stprefix := range []string{"stmm", "st"} { 1930 if strings.HasPrefix(reginfo.Name, stprefix) { 1931 idx, _ = strconv.Atoi(reginfo.Name[len(stprefix):]) 1932 break 1933 } 1934 } 1935 r = proc.AppendBytesRegister(r, fmt.Sprintf("ST(%d)", idx), regs.regs[reginfo.Name].value) 1936 1937 case reginfo.Bitsize == 128: 1938 if floatingPoint { 1939 name := reginfo.Name 1940 if last := name[len(name)-1]; last == 'h' || last == 'H' { 1941 name = name[:len(name)-1] 1942 } 1943 r = proc.AppendBytesRegister(r, strings.ToUpper(name), regs.regs[reginfo.Name].value) 1944 } 1945 1946 case reginfo.Bitsize == 256: 1947 if !strings.HasPrefix(strings.ToLower(reginfo.Name), "ymm") || !floatingPoint { 1948 continue 1949 } 1950 1951 value := regs.regs[reginfo.Name].value 1952 xmmName := "x" + reginfo.Name[1:] 1953 r = proc.AppendBytesRegister(r, strings.ToUpper(xmmName), value) 1954 1955 case reginfo.Bitsize == 512: 1956 if !strings.HasPrefix(strings.ToLower(reginfo.Name), "zmm") || !floatingPoint { 1957 continue 1958 } 1959 1960 value := regs.regs[reginfo.Name].value 1961 xmmName := "x" + reginfo.Name[1:] 1962 r = proc.AppendBytesRegister(r, strings.ToUpper(xmmName), value) 1963 } 1964 } 1965 return r, nil 1966 } 1967 1968 func (regs *gdbRegisters) Copy() (proc.Registers, error) { 1969 savedRegs := &gdbRegisters{} 1970 savedRegs.init(regs.regsInfo, regs.arch, regs.regnames) 1971 copy(savedRegs.buf, regs.buf) 1972 return savedRegs, nil 1973 } 1974 1975 func registerName(arch *proc.Arch, regNum uint64) string { 1976 regName, _, _ := arch.DwarfRegisterToString(int(regNum), nil) 1977 return strings.ToLower(regName) 1978 } 1979 1980 func machTargetExcToError(sig uint8) error { 1981 switch sig { 1982 case 0x91: 1983 return errors.New("bad access") 1984 case 0x92: 1985 return errors.New("bad instruction") 1986 case 0x93: 1987 return errors.New("arithmetic exception") 1988 case 0x94: 1989 return errors.New("emulation exception") 1990 case 0x95: 1991 return errors.New("software exception") 1992 case 0x96: 1993 return errors.New("breakpoint exception") 1994 } 1995 return nil 1996 } 1997 1998 // readG reads the G pointer on x86 by peeking the word before the TLS pointer. 1999 func (t *gdbThread) readG() error { 2000 var regnum int 2001 2002 switch t.p.bi.GOOS { 2003 case "windows": 2004 case "darwin": 2005 regnum = 59 // gs_base 2006 case "linux": 2007 regnum = 58 // fs_base 2008 default: 2009 panic("unsupported operating system attempting to find Goroutine on Thread") 2010 } 2011 2012 wordSize := t.p.bi.Arch.PtrSize() 2013 tls := make([]byte, wordSize) 2014 err := t.p.conn.readRegister(t.strID, regnum, tls) 2015 if err != nil { 2016 return err 2017 } 2018 2019 data := make([]byte, wordSize) 2020 tlsaddr := binary.LittleEndian.Uint64(tls) 2021 if tlsaddr == 0 { 2022 t.regs.tls = 0 2023 t.regs.gaddr = 0 2024 t.regs.hasgaddr = true 2025 return nil 2026 } 2027 2028 len, err := t.p.ReadMemory(data, tlsaddr-uint64(wordSize)) 2029 if err != nil { 2030 return err 2031 } 2032 if len != wordSize { 2033 return fmt.Errorf("too little data: only %d bytes", len) 2034 } 2035 2036 t.regs.tls = tlsaddr 2037 t.regs.gaddr = binary.LittleEndian.Uint64(data) 2038 t.regs.hasgaddr = true 2039 return nil 2040 }