You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

158 lines
3.8 KiB

  1. // Copyright 2018 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // +build linux
  15. package server
  16. import (
  17. "fmt"
  18. "os"
  19. "runtime"
  20. "syscall"
  21. "time"
  22. )
  23. // ptraceRun runs all the closures from fc on a dedicated OS thread. Errors
  24. // are returned on ec. Both channels must be unbuffered, to ensure that the
  25. // resultant error is sent back to the same goroutine that sent the closure.
  26. func ptraceRun(fc chan func() error, ec chan error) {
  27. if cap(fc) != 0 || cap(ec) != 0 {
  28. panic("ptraceRun was given buffered channels")
  29. }
  30. runtime.LockOSThread()
  31. for f := range fc {
  32. ec <- f()
  33. }
  34. }
  35. func (s *Server) startProcess(name string, argv []string, attr *os.ProcAttr) (proc *os.Process, err error) {
  36. s.fc <- func() error {
  37. var err1 error
  38. proc, err1 = os.StartProcess(name, argv, attr)
  39. return err1
  40. }
  41. err = <-s.ec
  42. return
  43. }
  44. func (s *Server) ptraceCont(pid int, signal int) (err error) {
  45. s.fc <- func() error {
  46. return syscall.PtraceCont(pid, signal)
  47. }
  48. return <-s.ec
  49. }
  50. func (s *Server) ptraceGetRegs(pid int, regsout *syscall.PtraceRegs) (err error) {
  51. s.fc <- func() error {
  52. return syscall.PtraceGetRegs(pid, regsout)
  53. }
  54. return <-s.ec
  55. }
  56. func (s *Server) ptracePeek(pid int, addr uintptr, out []byte) (err error) {
  57. s.fc <- func() error {
  58. n, err := syscall.PtracePeekText(pid, addr, out)
  59. if err != nil {
  60. return err
  61. }
  62. if n != len(out) {
  63. return fmt.Errorf("ptracePeek: peeked %d bytes, want %d", n, len(out))
  64. }
  65. return nil
  66. }
  67. return <-s.ec
  68. }
  69. func (s *Server) ptracePoke(pid int, addr uintptr, data []byte) (err error) {
  70. s.fc <- func() error {
  71. n, err := syscall.PtracePokeText(pid, addr, data)
  72. if err != nil {
  73. return err
  74. }
  75. if n != len(data) {
  76. return fmt.Errorf("ptracePoke: poked %d bytes, want %d", n, len(data))
  77. }
  78. return nil
  79. }
  80. return <-s.ec
  81. }
  82. func (s *Server) ptraceSetOptions(pid int, options int) (err error) {
  83. s.fc <- func() error {
  84. return syscall.PtraceSetOptions(pid, options)
  85. }
  86. return <-s.ec
  87. }
  88. func (s *Server) ptraceSetRegs(pid int, regs *syscall.PtraceRegs) (err error) {
  89. s.fc <- func() error {
  90. return syscall.PtraceSetRegs(pid, regs)
  91. }
  92. return <-s.ec
  93. }
  94. func (s *Server) ptraceSingleStep(pid int) (err error) {
  95. s.fc <- func() error {
  96. return syscall.PtraceSingleStep(pid)
  97. }
  98. return <-s.ec
  99. }
  100. type breakpointsChangedError struct {
  101. call call
  102. }
  103. func (*breakpointsChangedError) Error() string {
  104. return "breakpoints changed"
  105. }
  106. func (s *Server) wait(pid int, allowBreakpointsChange bool) (wpid int, status syscall.WaitStatus, err error) {
  107. // We poll syscall.Wait4 with WNOHANG, sleeping in between, as a poor man's
  108. // waitpid-with-timeout. This allows adding and removing breakpoints
  109. // concurrently with waiting to hit an existing breakpoint.
  110. f := func() error {
  111. var err1 error
  112. wpid, err1 = syscall.Wait4(pid, &status, syscall.WALL|syscall.WNOHANG, nil)
  113. return err1
  114. }
  115. const (
  116. minSleep = 1 * time.Microsecond
  117. maxSleep = 100 * time.Millisecond
  118. )
  119. for sleep := minSleep; ; {
  120. s.fc <- f
  121. err = <-s.ec
  122. // wpid == 0 means that wait found nothing (and returned due to WNOHANG).
  123. if wpid != 0 {
  124. return
  125. }
  126. if allowBreakpointsChange {
  127. select {
  128. case c := <-s.breakpointc:
  129. return 0, 0, &breakpointsChangedError{c}
  130. default:
  131. }
  132. }
  133. time.Sleep(sleep)
  134. if sleep < maxSleep {
  135. sleep *= 10
  136. }
  137. }
  138. }