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

Side by Side Diff: program/server/server.go

Issue 85860043: code review 85860043: ogle: new arch package for architecture-dependent details (Closed)
Patch Set: 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:
View unified diff | Download patch
« arch/arch.go ('K') | « arch/arch.go ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "encoding/binary"
11 "fmt" 10 "fmt"
12 "os" 11 "os"
13 "regexp" 12 "regexp"
14 "strconv" 13 "strconv"
15 "strings" 14 "strings"
16 "sync" 15 "sync"
17 "syscall" 16 "syscall"
18 17
19 "code.google.com/p/ogle/debug/dwarf" 18 "code.google.com/p/ogle/debug/dwarf"
20 "code.google.com/p/ogle/debug/elf" 19 "code.google.com/p/ogle/debug/elf"
21 "code.google.com/p/ogle/debug/macho" 20 "code.google.com/p/ogle/debug/macho"
22 21
22 "code.google.com/p/ogle/arch"
23 "code.google.com/p/ogle/program" 23 "code.google.com/p/ogle/program"
24 "code.google.com/p/ogle/program/proxyrpc" 24 "code.google.com/p/ogle/program/proxyrpc"
25 ) 25 )
26 26
27 type breakpoint struct { 27 type breakpoint struct {
28 pc uint64 28 pc uint64
29 » origInstr byte // TODO: don't be amd64-specific. 29 » origInstr [arch.MaxBreakpointSize]byte
30 } 30 }
31 31
32 type Server struct { 32 type Server struct {
33 arch arch.Architecture
33 executable string // Name of executable. 34 executable string // Name of executable.
34 dwarfData *dwarf.Data 35 dwarfData *dwarf.Data
35 36
36 mu sync.Mutex 37 mu sync.Mutex
37 38
38 fc chan func() error 39 fc chan func() error
39 ec chan error 40 ec chan error
40 41
41 proc *os.Process 42 proc *os.Process
42 breakpoints map[uint64]breakpoint 43 breakpoints map[uint64]breakpoint
43 files []*file // Index == file descriptor. 44 files []*file // Index == file descriptor.
44 } 45 }
45 46
46 // New parses the executable and builds local data structures for answering requ ests. 47 // New parses the executable and builds local data structures for answering requ ests.
47 // It returns a Server ready to serve requests about the executable. 48 // It returns a Server ready to serve requests about the executable.
48 func New(executable string) (*Server, error) { 49 func New(executable string) (*Server, error) {
49 fd, err := os.Open(executable) 50 fd, err := os.Open(executable)
50 if err != nil { 51 if err != nil {
51 return nil, err 52 return nil, err
52 } 53 }
53 defer fd.Close() 54 defer fd.Close()
54 dwarfData, err := loadDwarfData(fd) 55 dwarfData, err := loadDwarfData(fd)
55 if err != nil { 56 if err != nil {
56 return nil, err 57 return nil, err
57 } 58 }
58 srv := &Server{ 59 srv := &Server{
60 arch: arch.AMD64, // TODO: How do we discover this?
59 executable: executable, 61 executable: executable,
60 dwarfData: dwarfData, 62 dwarfData: dwarfData,
61 fc: make(chan func() error), 63 fc: make(chan func() error),
62 ec: make(chan error), 64 ec: make(chan error),
63 breakpoints: make(map[uint64]breakpoint), 65 breakpoints: make(map[uint64]breakpoint),
64 } 66 }
65 go ptraceRun(srv.fc, srv.ec) 67 go ptraceRun(srv.fc, srv.ec)
66 return srv, nil 68 return srv, nil
67 } 69 }
68 70
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 err = s.liftBreakpoints() 213 err = s.liftBreakpoints()
212 if err != nil { 214 if err != nil {
213 return err 215 return err
214 } 216 }
215 217
216 err = s.ptraceGetRegs(s.proc.Pid, &regs) 218 err = s.ptraceGetRegs(s.proc.Pid, &regs)
217 if err != nil { 219 if err != nil {
218 return err 220 return err
219 } 221 }
220 222
221 » regs.Rip-- // TODO: depends on length of trap. 223 » regs.Rip -= uint64(s.arch.BreakpointSize)
222 err = s.ptraceSetRegs(s.proc.Pid, &regs) 224 err = s.ptraceSetRegs(s.proc.Pid, &regs)
223 if err != nil { 225 if err != nil {
224 return fmt.Errorf("ptraceSetRegs: %v", err) 226 return fmt.Errorf("ptraceSetRegs: %v", err)
225 } 227 }
226 228
227 resp.Status.PC = regs.Rip 229 resp.Status.PC = regs.Rip
228 resp.Status.SP = regs.Rsp 230 resp.Status.SP = regs.Rsp
229 return nil 231 return nil
230 } 232 }
231 233
232 func (s *Server) Breakpoint(req *proxyrpc.BreakpointRequest, resp *proxyrpc.Brea kpointResponse) (err error) { 234 func (s *Server) Breakpoint(req *proxyrpc.BreakpointRequest, resp *proxyrpc.Brea kpointResponse) (err error) {
233 s.mu.Lock() 235 s.mu.Lock()
234 defer s.mu.Unlock() 236 defer s.mu.Unlock()
235 237
236 addrs, err := s.eval(req.Address) 238 addrs, err := s.eval(req.Address)
237 if err != nil { 239 if err != nil {
238 return err 240 return err
239 } 241 }
242 var bp breakpoint
240 for _, addr := range addrs { 243 for _, addr := range addrs {
241 pc, err := s.evalAddress(addr) 244 pc, err := s.evalAddress(addr)
242 if err != nil { 245 if err != nil {
243 return err 246 return err
244 } 247 }
245 if _, alreadySet := s.breakpoints[pc]; alreadySet { 248 if _, alreadySet := s.breakpoints[pc]; alreadySet {
246 return fmt.Errorf("breakpoint already set at %#x (TODO)" , pc) 249 return fmt.Errorf("breakpoint already set at %#x (TODO)" , pc)
247 } 250 }
248 251
249 » » var buf [1]byte 252 » » err = s.ptracePeek(s.proc.Pid, uintptr(pc), bp.origInstr[:s.arch .BreakpointSize])
250 » » err = s.ptracePeek(s.proc.Pid, uintptr(pc), buf[:])
251 if err != nil { 253 if err != nil {
252 » » » return fmt.Errorf("ptracePoke: %v", err) 254 » » » return fmt.Errorf("ptracePeek: %v", err)
253 } 255 }
254 » » s.breakpoints[pc] = breakpoint{pc: pc, origInstr: buf[0]} 256 » » bp.pc = pc
257 » » s.breakpoints[pc] = bp
255 } 258 }
256 259
257 return nil 260 return nil
258 } 261 }
259 262
260 func (s *Server) setBreakpoints() error { 263 func (s *Server) setBreakpoints() error {
261 var buf [1]byte
262 buf[0] = 0xcc // INT 3 instruction on x86.
263 for pc := range s.breakpoints { 264 for pc := range s.breakpoints {
264 » » err := s.ptracePoke(s.proc.Pid, uintptr(pc), buf[:]) 265 » » err := s.ptracePoke(s.proc.Pid, uintptr(pc), s.arch.BreakpointIn str[:])
nigeltao 2014/04/09 05:23:49 Drop the "[:]".
265 if err != nil { 266 if err != nil {
266 return fmt.Errorf("setBreakpoints: %v", err) 267 return fmt.Errorf("setBreakpoints: %v", err)
267 } 268 }
268 } 269 }
269 return nil 270 return nil
270 } 271 }
271 272
272 func (s *Server) liftBreakpoints() error { 273 func (s *Server) liftBreakpoints() error {
273 var buf [1]byte
274 for pc, breakpoint := range s.breakpoints { 274 for pc, breakpoint := range s.breakpoints {
275 » » buf[0] = breakpoint.origInstr 275 » » err := s.ptracePoke(s.proc.Pid, uintptr(pc), breakpoint.origInst r[:])
nigeltao 2014/04/09 05:23:49 breakpoint.origInstr[:s.arch.BreakpointSize]
276 » » err := s.ptracePoke(s.proc.Pid, uintptr(pc), buf[:])
277 if err != nil { 276 if err != nil {
278 return fmt.Errorf("liftBreakpoints: %v", err) 277 return fmt.Errorf("liftBreakpoints: %v", err)
279 } 278 }
280 } 279 }
281 return nil 280 return nil
282 } 281 }
283 282
284 func (s *Server) Eval(req *proxyrpc.EvalRequest, resp *proxyrpc.EvalResponse) (e rr error) { 283 func (s *Server) Eval(req *proxyrpc.EvalRequest, resp *proxyrpc.EvalResponse) (e rr error) {
285 s.mu.Lock() 284 s.mu.Lock()
286 defer s.mu.Unlock() 285 defer s.mu.Unlock()
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 return fmt.Errorf("Frames.Count != 1 is not implemented") 352 return fmt.Errorf("Frames.Count != 1 is not implemented")
354 } 353 }
355 354
356 // TODO: we're assuming we're at a function's entry point (LowPC). 355 // TODO: we're assuming we're at a function's entry point (LowPC).
357 356
358 regs := syscall.PtraceRegs{} 357 regs := syscall.PtraceRegs{}
359 err := s.ptraceGetRegs(s.proc.Pid, &regs) 358 err := s.ptraceGetRegs(s.proc.Pid, &regs)
360 if err != nil { 359 if err != nil {
361 return err 360 return err
362 } 361 }
363 » fp := regs.Rsp + 8 // TODO: 8 for the return address is amd64 specific. 362 » fp := regs.Rsp + uint64(s.arch.PointerSize)
364 363
365 entry, err := s.entryForPC(regs.Rip) 364 entry, err := s.entryForPC(regs.Rip)
366 if err != nil { 365 if err != nil {
367 return err 366 return err
368 } 367 }
369 368
370 var buf [8]byte 369 var buf [8]byte
371 frame := program.Frame{} 370 frame := program.Frame{}
372 r := s.dwarfData.Reader() 371 r := s.dwarfData.Reader()
373 r.Seek(entry.Offset) 372 r.Seek(entry.Offset)
(...skipping 20 matching lines...) Expand all
394 offset := evalLocation(f.Val.([]uint8)) 393 offset := evalLocation(f.Val.([]uint8))
395 location = uintptr(int64(fp) + offset) 394 location = uintptr(int64(fp) + offset)
396 frame.S += fmt.Sprintf("(%d(FP))", offset) 395 frame.S += fmt.Sprintf("(%d(FP))", offset)
397 case dwarf.AttrName: 396 case dwarf.AttrName:
398 frame.S += " " + f.Val.(string) 397 frame.S += " " + f.Val.(string)
399 case dwarf.AttrType: 398 case dwarf.AttrType:
400 t, err := s.dwarfData.Type(f.Val.(dwarf.Offset)) 399 t, err := s.dwarfData.Type(f.Val.(dwarf.Offset))
401 if err == nil { 400 if err == nil {
402 frame.S += fmt.Sprintf("[%v]", t) 401 frame.S += fmt.Sprintf("[%v]", t)
403 } 402 }
404 » » » » // TODO: don't assume amd64. 403 » » » » if t.String() != "int" || t.Size() != int64(s.ar ch.IntSize) {
405 » » » » if t.String() != "int" && t.Size() == 8 {
406 break 404 break
407 } 405 }
408 if location == 0 { 406 if location == 0 {
409 return fmt.Errorf("no location for Forma lParameter") 407 return fmt.Errorf("no location for Forma lParameter")
410 } 408 }
411 » » » » err = s.ptracePeek(s.proc.Pid, location, buf[:8] ) 409 » » » » err = s.ptracePeek(s.proc.Pid, location, buf[:s. arch.IntSize])
412 if err != nil { 410 if err != nil {
413 return err 411 return err
414 } 412 }
415 » » » » // TODO: don't assume little-endian. 413 » » » » frame.S += fmt.Sprintf("==%#x", s.arch.Int(buf[: s.arch.IntSize]))
416 » » » » frame.S += fmt.Sprintf("==%#x", binary.LittleEnd ian.Uint64(buf[:8]))
417 } 414 }
418 } 415 }
419 } 416 }
420 resp.Frames = append(resp.Frames, frame) 417 resp.Frames = append(resp.Frames, frame)
421 return nil 418 return nil
422 } 419 }
OLDNEW
« arch/arch.go ('K') | « arch/arch.go ('k') | no next file » | no next file with comments »

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