OLD | NEW |
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" |
10 "fmt" | 11 "fmt" |
11 "os" | 12 "os" |
12 "regexp" | 13 "regexp" |
13 "strconv" | 14 "strconv" |
14 "strings" | 15 "strings" |
15 "sync" | 16 "sync" |
16 "syscall" | 17 "syscall" |
17 | 18 |
18 "code.google.com/p/ogle/debug/dwarf" | 19 "code.google.com/p/ogle/debug/dwarf" |
19 "code.google.com/p/ogle/debug/elf" | 20 "code.google.com/p/ogle/debug/elf" |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 } | 322 } |
322 | 323 |
323 // Must be a number. | 324 // Must be a number. |
324 addr, err = strconv.ParseUint(expr, 0, 0) | 325 addr, err = strconv.ParseUint(expr, 0, 0) |
325 if err != nil { | 326 if err != nil { |
326 return 0, fmt.Errorf("eval: %q is neither symbol nor number", ex
pr) | 327 return 0, fmt.Errorf("eval: %q is neither symbol nor number", ex
pr) |
327 } | 328 } |
328 | 329 |
329 return addr, nil | 330 return addr, nil |
330 } | 331 } |
| 332 |
| 333 func (s *Server) Frames(req *proxyrpc.FramesRequest, resp *proxyrpc.FramesRespon
se) error { |
| 334 // TODO: verify that we're stopped. |
| 335 s.mu.Lock() |
| 336 defer s.mu.Unlock() |
| 337 |
| 338 if req.Count != 1 { |
| 339 // TODO: implement. |
| 340 return fmt.Errorf("Frames.Count != 1 is not implemented") |
| 341 } |
| 342 |
| 343 // TODO: we're assuming we're at a function's entry point (LowPC). |
| 344 |
| 345 regs := syscall.PtraceRegs{} |
| 346 err := s.ptraceGetRegs(s.proc.Pid, ®s) |
| 347 if err != nil { |
| 348 return err |
| 349 } |
| 350 fp := regs.Rsp + 8 // TODO: 8 for the return address is amd64 specific. |
| 351 |
| 352 // TODO: the -1 on the next line backs up the INT3 breakpoint. Should it
be there? |
| 353 entry, err := s.entryForPC(regs.Rip - 1) |
| 354 if err != nil { |
| 355 return err |
| 356 } |
| 357 |
| 358 var buf [8]byte |
| 359 frame := program.Frame{} |
| 360 r := s.dwarfData.Reader() |
| 361 r.Seek(entry.Offset) |
| 362 for { |
| 363 entry, err := r.Next() |
| 364 if err != nil { |
| 365 return err |
| 366 } |
| 367 if entry.Tag == 0 { |
| 368 break |
| 369 } |
| 370 if entry.Tag != dwarf.TagFormalParameter { |
| 371 continue |
| 372 } |
| 373 if entry.Children { |
| 374 // TODO: handle this?? |
| 375 return fmt.Errorf("FormalParameter has children, expecte
d none") |
| 376 } |
| 377 // TODO: the returned frame should be structured instead of a ha
cked up string. |
| 378 location := uintptr(0) |
| 379 for _, f := range entry.Field { |
| 380 switch f.Attr { |
| 381 case dwarf.AttrLocation: |
| 382 offset := evalLocation(f.Val.([]uint8)) |
| 383 location = uintptr(int64(fp) + offset) |
| 384 frame.S += fmt.Sprintf("(%d(FP))", offset) |
| 385 case dwarf.AttrName: |
| 386 frame.S += " " + f.Val.(string) |
| 387 case dwarf.AttrType: |
| 388 t, err := s.dwarfData.Type(f.Val.(dwarf.Offset)) |
| 389 if err == nil { |
| 390 frame.S += fmt.Sprintf("[%v]", t) |
| 391 } |
| 392 // TODO: don't assume amd64. |
| 393 if t.String() != "int" && t.Size() == 8 { |
| 394 break |
| 395 } |
| 396 if location == 0 { |
| 397 return fmt.Errorf("no location for Forma
lParameter") |
| 398 } |
| 399 err = s.ptracePeek(s.proc.Pid, location, buf[:8]
) |
| 400 if err != nil { |
| 401 return err |
| 402 } |
| 403 // TODO: don't assume little-endian. |
| 404 frame.S += fmt.Sprintf("==%#x", binary.LittleEnd
ian.Uint64(buf[:8])) |
| 405 } |
| 406 } |
| 407 } |
| 408 resp.Frames = append(resp.Frames, frame) |
| 409 return nil |
| 410 } |
OLD | NEW |