LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2014 The Go Authors. All rights reserved. | 1 // Copyright 2014 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Package server provides RPC access to a local program being debugged. | 5 // Package server provides RPC access to a local program being debugged. |
6 // It is the remote end of the client implementation of the Program interface. | 6 // It is the remote end of the client implementation of the Program interface. |
7 package server | 7 package server |
8 | 8 |
9 import ( | 9 import ( |
10 "fmt" | 10 "fmt" |
(...skipping 22 matching lines...) Expand all Loading... |
33 arch arch.Architecture | 33 arch arch.Architecture |
34 executable string // Name of executable. | 34 executable string // Name of executable. |
35 dwarfData *dwarf.Data | 35 dwarfData *dwarf.Data |
36 | 36 |
37 mu sync.Mutex | 37 mu sync.Mutex |
38 | 38 |
39 fc chan func() error | 39 fc chan func() error |
40 ec chan error | 40 ec chan error |
41 | 41 |
42 proc *os.Process | 42 proc *os.Process |
| 43 procIsUp bool |
| 44 stoppedPid int |
| 45 stoppedRegs syscall.PtraceRegs |
43 breakpoints map[uint64]breakpoint | 46 breakpoints map[uint64]breakpoint |
44 files []*file // Index == file descriptor. | 47 files []*file // Index == file descriptor. |
45 } | 48 } |
46 | 49 |
47 // New parses the executable and builds local data structures for answering requ
ests. | 50 // New parses the executable and builds local data structures for answering requ
ests. |
48 // It returns a Server ready to serve requests about the executable. | 51 // It returns a Server ready to serve requests about the executable. |
49 func New(executable string) (*Server, error) { | 52 func New(executable string) (*Server, error) { |
50 fd, err := os.Open(executable) | 53 fd, err := os.Open(executable) |
51 if err != nil { | 54 if err != nil { |
52 return nil, err | 55 return nil, err |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 return err | 179 return err |
177 } | 180 } |
178 | 181 |
179 func (s *Server) Run(req *proxyrpc.RunRequest, resp *proxyrpc.RunResponse) error
{ | 182 func (s *Server) Run(req *proxyrpc.RunRequest, resp *proxyrpc.RunResponse) error
{ |
180 s.mu.Lock() | 183 s.mu.Lock() |
181 defer s.mu.Unlock() | 184 defer s.mu.Unlock() |
182 | 185 |
183 if s.proc != nil { | 186 if s.proc != nil { |
184 s.proc.Kill() | 187 s.proc.Kill() |
185 s.proc = nil | 188 s.proc = nil |
| 189 s.procIsUp = false |
| 190 s.stoppedPid = 0 |
| 191 s.stoppedRegs = syscall.PtraceRegs{} |
186 } | 192 } |
187 p, err := s.startProcess(s.executable, nil, &os.ProcAttr{ | 193 p, err := s.startProcess(s.executable, nil, &os.ProcAttr{ |
188 Files: []*os.File{ | 194 Files: []*os.File{ |
189 nil, // TODO: be able to feed the target's stdin. | 195 nil, // TODO: be able to feed the target's stdin. |
190 os.Stderr, // TODO: be able to capture the target's stdo
ut. | 196 os.Stderr, // TODO: be able to capture the target's stdo
ut. |
191 os.Stderr, | 197 os.Stderr, |
192 }, | 198 }, |
193 Sys: &syscall.SysProcAttr{ | 199 Sys: &syscall.SysProcAttr{ |
194 » » » Ptrace: !req.Start, | 200 » » » Pdeathsig: syscall.SIGKILL, |
| 201 » » » Ptrace: true, |
195 }, | 202 }, |
196 }) | 203 }) |
197 if err != nil { | 204 if err != nil { |
198 return err | 205 return err |
199 } | 206 } |
200 s.proc = p | 207 s.proc = p |
201 | 208 » s.stoppedPid = p.Pid |
202 » if !req.Start { | |
203 » » // TODO: wait until /proc/{s.proc.Pid}/status says "State:»
t (tracing stop)". | |
204 » } | |
205 return nil | 209 return nil |
206 } | 210 } |
207 | 211 |
208 func (s *Server) Resume(req *proxyrpc.ResumeRequest, resp *proxyrpc.ResumeRespon
se) error { | 212 func (s *Server) Resume(req *proxyrpc.ResumeRequest, resp *proxyrpc.ResumeRespon
se) error { |
209 s.mu.Lock() | 213 s.mu.Lock() |
210 defer s.mu.Unlock() | 214 defer s.mu.Unlock() |
211 | 215 |
212 » regs := syscall.PtraceRegs{} | 216 » if s.proc == nil { |
213 » err := s.ptraceGetRegs(s.proc.Pid, ®s) | 217 » » return fmt.Errorf("Resume: Run did not successfully start a proc
ess") |
214 » if err != nil { | 218 » } |
215 » » return err | 219 |
216 » } | 220 » if !s.procIsUp { |
217 » if _, ok := s.breakpoints[regs.Rip]; ok { | 221 » » s.procIsUp = true |
218 » » err = s.ptraceSingleStep(s.proc.Pid) | 222 » » _, err := s.waitForTrap(s.stoppedPid) |
| 223 » » if err != nil { |
| 224 » » » return err |
| 225 » » } |
| 226 » » err = s.ptraceSetOptions(s.stoppedPid, syscall.PTRACE_O_TRACECLO
NE) |
| 227 » » if err != nil { |
| 228 » » » return fmt.Errorf("ptraceSetOptions: %v", err) |
| 229 » » } |
| 230 » } else if _, ok := s.breakpoints[s.stoppedRegs.Rip]; ok { |
| 231 » » err := s.ptraceSingleStep(s.stoppedPid) |
219 if err != nil { | 232 if err != nil { |
220 return fmt.Errorf("ptraceSingleStep: %v", err) | 233 return fmt.Errorf("ptraceSingleStep: %v", err) |
221 } | 234 } |
222 » } | 235 » » _, err = s.waitForTrap(s.stoppedPid) |
223 | 236 » » if err != nil { |
224 » err = s.setBreakpoints() | 237 » » » return err |
225 » if err != nil { | 238 » » } |
226 » » return err | 239 » } |
227 » } | 240 |
228 | 241 » err := s.setBreakpoints() |
229 » err = s.ptraceCont(s.proc.Pid, 0) | 242 » if err != nil { |
230 » if err != nil { | 243 » » return err |
231 » » return err | 244 » } |
232 » } | 245 » err = s.ptraceCont(s.stoppedPid, 0) |
233 | 246 » if err != nil { |
234 » err = s.wait() | 247 » » return fmt.Errorf("ptraceCont: %v", err) |
| 248 » } |
| 249 |
| 250 » s.stoppedPid, err = s.waitForTrap(-1) |
235 if err != nil { | 251 if err != nil { |
236 return err | 252 return err |
237 } | 253 } |
238 | 254 |
239 err = s.liftBreakpoints() | 255 err = s.liftBreakpoints() |
240 if err != nil { | 256 if err != nil { |
241 return err | 257 return err |
242 } | 258 } |
243 | 259 |
244 » err = s.ptraceGetRegs(s.proc.Pid, ®s) | 260 » err = s.ptraceGetRegs(s.stoppedPid, &s.stoppedRegs) |
245 » if err != nil { | 261 » if err != nil { |
246 » » return err | 262 » » return fmt.Errorf("ptraceGetRegs: %v", err) |
247 » } | 263 » } |
248 | 264 |
249 » regs.Rip -= uint64(s.arch.BreakpointSize) | 265 » s.stoppedRegs.Rip -= uint64(s.arch.BreakpointSize) |
250 » err = s.ptraceSetRegs(s.proc.Pid, ®s) | 266 |
| 267 » err = s.ptraceSetRegs(s.stoppedPid, &s.stoppedRegs) |
251 if err != nil { | 268 if err != nil { |
252 return fmt.Errorf("ptraceSetRegs: %v", err) | 269 return fmt.Errorf("ptraceSetRegs: %v", err) |
253 } | 270 } |
254 | 271 |
255 » resp.Status.PC = regs.Rip | 272 » resp.Status.PC = s.stoppedRegs.Rip |
256 » resp.Status.SP = regs.Rsp | 273 » resp.Status.SP = s.stoppedRegs.Rsp |
257 » return nil | 274 » return nil |
| 275 } |
| 276 |
| 277 func (s *Server) waitForTrap(pid int) (wpid int, err error) { |
| 278 » for { |
| 279 » » wpid, status, err := s.wait(pid) |
| 280 » » if err != nil { |
| 281 » » » return 0, fmt.Errorf("wait: %v", err) |
| 282 » » } |
| 283 » » if status.StopSignal() == syscall.SIGTRAP && status.TrapCause()
!= syscall.PTRACE_EVENT_CLONE { |
| 284 » » » return wpid, nil |
| 285 » » } |
| 286 » » err = s.ptraceCont(wpid, 0) // TODO: non-zero when wait catches
other signals? |
| 287 » » if err != nil { |
| 288 » » » return 0, fmt.Errorf("ptraceCont: %v", err) |
| 289 » » } |
| 290 » } |
258 } | 291 } |
259 | 292 |
260 func (s *Server) Breakpoint(req *proxyrpc.BreakpointRequest, resp *proxyrpc.Brea
kpointResponse) (err error) { | 293 func (s *Server) Breakpoint(req *proxyrpc.BreakpointRequest, resp *proxyrpc.Brea
kpointResponse) (err error) { |
261 s.mu.Lock() | 294 s.mu.Lock() |
262 defer s.mu.Unlock() | 295 defer s.mu.Unlock() |
263 | 296 |
264 addrs, err := s.eval(req.Address) | 297 addrs, err := s.eval(req.Address) |
265 if err != nil { | 298 if err != nil { |
266 return err | 299 return err |
267 } | 300 } |
268 var bp breakpoint | 301 var bp breakpoint |
269 for _, addr := range addrs { | 302 for _, addr := range addrs { |
270 pc, err := s.evalAddress(addr) | 303 pc, err := s.evalAddress(addr) |
271 if err != nil { | 304 if err != nil { |
272 return err | 305 return err |
273 } | 306 } |
274 if _, alreadySet := s.breakpoints[pc]; alreadySet { | 307 if _, alreadySet := s.breakpoints[pc]; alreadySet { |
275 return fmt.Errorf("breakpoint already set at %#x (TODO)"
, pc) | 308 return fmt.Errorf("breakpoint already set at %#x (TODO)"
, pc) |
276 } | 309 } |
277 | 310 |
278 » » err = s.ptracePeek(s.proc.Pid, uintptr(pc), bp.origInstr[:s.arch
.BreakpointSize]) | 311 » » err = s.ptracePeek(s.stoppedPid, uintptr(pc), bp.origInstr[:s.ar
ch.BreakpointSize]) |
279 if err != nil { | 312 if err != nil { |
280 return fmt.Errorf("ptracePeek: %v", err) | 313 return fmt.Errorf("ptracePeek: %v", err) |
281 } | 314 } |
282 bp.pc = pc | 315 bp.pc = pc |
283 s.breakpoints[pc] = bp | 316 s.breakpoints[pc] = bp |
284 } | 317 } |
285 | 318 |
286 return nil | 319 return nil |
287 } | 320 } |
288 | 321 |
289 func (s *Server) setBreakpoints() error { | 322 func (s *Server) setBreakpoints() error { |
290 for pc := range s.breakpoints { | 323 for pc := range s.breakpoints { |
291 » » err := s.ptracePoke(s.proc.Pid, uintptr(pc), s.arch.BreakpointIn
str[:s.arch.BreakpointSize]) | 324 » » err := s.ptracePoke(s.stoppedPid, uintptr(pc), s.arch.Breakpoint
Instr[:s.arch.BreakpointSize]) |
292 if err != nil { | 325 if err != nil { |
293 return fmt.Errorf("setBreakpoints: %v", err) | 326 return fmt.Errorf("setBreakpoints: %v", err) |
294 } | 327 } |
295 } | 328 } |
296 return nil | 329 return nil |
297 } | 330 } |
298 | 331 |
299 func (s *Server) liftBreakpoints() error { | 332 func (s *Server) liftBreakpoints() error { |
300 for pc, breakpoint := range s.breakpoints { | 333 for pc, breakpoint := range s.breakpoints { |
301 » » err := s.ptracePoke(s.proc.Pid, uintptr(pc), breakpoint.origInst
r[:s.arch.BreakpointSize]) | 334 » » err := s.ptracePoke(s.stoppedPid, uintptr(pc), breakpoint.origIn
str[:s.arch.BreakpointSize]) |
302 if err != nil { | 335 if err != nil { |
303 return fmt.Errorf("liftBreakpoints: %v", err) | 336 return fmt.Errorf("liftBreakpoints: %v", err) |
304 } | 337 } |
305 } | 338 } |
306 return nil | 339 return nil |
307 } | 340 } |
308 | 341 |
309 func (s *Server) Eval(req *proxyrpc.EvalRequest, resp *proxyrpc.EvalResponse) (e
rr error) { | 342 func (s *Server) Eval(req *proxyrpc.EvalRequest, resp *proxyrpc.EvalResponse) (e
rr error) { |
310 s.mu.Lock() | 343 s.mu.Lock() |
311 defer s.mu.Unlock() | 344 defer s.mu.Unlock() |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 defer s.mu.Unlock() | 407 defer s.mu.Unlock() |
375 | 408 |
376 if req.Count != 1 { | 409 if req.Count != 1 { |
377 // TODO: implement. | 410 // TODO: implement. |
378 return fmt.Errorf("Frames.Count != 1 is not implemented") | 411 return fmt.Errorf("Frames.Count != 1 is not implemented") |
379 } | 412 } |
380 | 413 |
381 // TODO: we're assuming we're at a function's entry point (LowPC). | 414 // TODO: we're assuming we're at a function's entry point (LowPC). |
382 | 415 |
383 regs := syscall.PtraceRegs{} | 416 regs := syscall.PtraceRegs{} |
384 » err := s.ptraceGetRegs(s.proc.Pid, ®s) | 417 » err := s.ptraceGetRegs(s.stoppedPid, ®s) |
385 if err != nil { | 418 if err != nil { |
386 return err | 419 return err |
387 } | 420 } |
388 fp := regs.Rsp + uint64(s.arch.PointerSize) | 421 fp := regs.Rsp + uint64(s.arch.PointerSize) |
389 | 422 |
390 entry, err := s.entryForPC(regs.Rip) | 423 entry, err := s.entryForPC(regs.Rip) |
391 if err != nil { | 424 if err != nil { |
392 return err | 425 return err |
393 } | 426 } |
394 | 427 |
(...skipping 30 matching lines...) Expand all Loading... |
425 t, err := s.dwarfData.Type(f.Val.(dwarf.Offset)) | 458 t, err := s.dwarfData.Type(f.Val.(dwarf.Offset)) |
426 if err == nil { | 459 if err == nil { |
427 frame.S += fmt.Sprintf("[%v]", t) | 460 frame.S += fmt.Sprintf("[%v]", t) |
428 } | 461 } |
429 if t.String() != "int" || t.Size() != int64(s.ar
ch.IntSize) { | 462 if t.String() != "int" || t.Size() != int64(s.ar
ch.IntSize) { |
430 break | 463 break |
431 } | 464 } |
432 if location == 0 { | 465 if location == 0 { |
433 return fmt.Errorf("no location for Forma
lParameter") | 466 return fmt.Errorf("no location for Forma
lParameter") |
434 } | 467 } |
435 » » » » err = s.ptracePeek(s.proc.Pid, location, buf[:s.
arch.IntSize]) | 468 » » » » err = s.ptracePeek(s.stoppedPid, location, buf[:
s.arch.IntSize]) |
436 if err != nil { | 469 if err != nil { |
437 return err | 470 return err |
438 } | 471 } |
439 frame.S += fmt.Sprintf("==%#x", s.arch.Int(buf[:
s.arch.IntSize])) | 472 frame.S += fmt.Sprintf("==%#x", s.arch.Int(buf[:
s.arch.IntSize])) |
440 } | 473 } |
441 } | 474 } |
442 } | 475 } |
443 resp.Frames = append(resp.Frames, frame) | 476 resp.Frames = append(resp.Frames, frame) |
444 return nil | 477 return nil |
445 } | 478 } |
LEFT | RIGHT |