Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(287)

Delta Between Two Patch Sets: program/server/server.go

Issue 86370043: code review 86370043: program: trace multi-threaded programs. (Closed)
Left Patch Set: Created 9 years, 11 months ago
Right Patch Set: diff -r f3347973b1cb https://code.google.com/p/ogle Created 9 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « program/server/ptrace.go ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(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
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
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, &regs) 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, &regs) 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, &regs) 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
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, &regs) 417 » err := s.ptraceGetRegs(s.stoppedPid, &regs)
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
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 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b