1// Copyright 2019 Google LLC
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
15// +build linux
16
17// Package server provides RPC access to a local program being debugged.
18// It is the remote end of the client implementation of the Program interface.
19package server
20
21//go:generate sh -c "m4 -P eval.m4 > eval.go"
22
23import (
24	"bytes"
25	"errors"
26	"fmt"
27	"os"
28	"regexp"
29	"strconv"
30	"strings"
31	"sync"
32	"syscall"
33
34	"cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug"
35	"cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/arch"
36	"cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/dwarf"
37	"cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/elf"
38	"cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/server/protocol"
39)
40
41type breakpoint struct {
42	pc        uint64
43	origInstr [arch.MaxBreakpointSize]byte
44}
45
46type call struct {
47	req, resp interface{}
48	errc      chan error
49}
50
51type Server struct {
52	arch       arch.Architecture
53	executable string // Name of executable.
54	dwarfData  *dwarf.Data
55
56	breakpointc chan call
57	otherc      chan call
58
59	fc chan func() error
60	ec chan error
61
62	proc            *os.Process
63	procIsUp        bool
64	stoppedPid      int
65	stoppedRegs     syscall.PtraceRegs
66	topOfStackAddrs []uint64
67	breakpoints     map[uint64]breakpoint
68	files           []*file // Index == file descriptor.
69	printer         *Printer
70
71	// goroutineStack reads the stack of a (non-running) goroutine.
72	goroutineStack     func(uint64) ([]debug.Frame, error)
73	goroutineStackOnce sync.Once
74}
75
76// peek implements the Peeker interface required by the printer.
77func (s *Server) peek(offset uintptr, buf []byte) error {
78	return s.ptracePeek(s.stoppedPid, offset, buf)
79}
80
81// New parses the executable and builds local data structures for answering requests.
82// It returns a Server ready to serve requests about the executable.
83func New(executable string) (*Server, error) {
84	fd, err := os.Open(executable)
85	if err != nil {
86		return nil, err
87	}
88	defer fd.Close()
89	architecture, dwarfData, err := loadExecutable(fd)
90	if err != nil {
91		return nil, err
92	}
93	srv := &Server{
94		arch:        *architecture,
95		executable:  executable,
96		dwarfData:   dwarfData,
97		breakpointc: make(chan call),
98		otherc:      make(chan call),
99		fc:          make(chan func() error),
100		ec:          make(chan error),
101		breakpoints: make(map[uint64]breakpoint),
102	}
103	srv.printer = NewPrinter(architecture, dwarfData, srv)
104	go ptraceRun(srv.fc, srv.ec)
105	go srv.loop()
106	return srv, nil
107}
108
109func loadExecutable(f *os.File) (*arch.Architecture, *dwarf.Data, error) {
110	// TODO: How do we detect NaCl?
111	if obj, err := elf.NewFile(f); err == nil {
112		dwarfData, err := obj.DWARF()
113		if err != nil {
114			return nil, nil, err
115		}
116
117		switch obj.Machine {
118		case elf.EM_ARM:
119			return &arch.ARM, dwarfData, nil
120		case elf.EM_386:
121			switch obj.Class {
122			case elf.ELFCLASS32:
123				return &arch.X86, dwarfData, nil
124			case elf.ELFCLASS64:
125				return &arch.AMD64, dwarfData, nil
126			}
127		case elf.EM_X86_64:
128			return &arch.AMD64, dwarfData, nil
129		}
130		return nil, nil, fmt.Errorf("unrecognized ELF architecture")
131	}
132	return nil, nil, fmt.Errorf("unrecognized binary format")
133}
134
135func (s *Server) loop() {
136	for {
137		var c call
138		select {
139		case c = <-s.breakpointc:
140		case c = <-s.otherc:
141		}
142		s.dispatch(c)
143	}
144}
145
146func (s *Server) dispatch(c call) {
147	switch req := c.req.(type) {
148	case *protocol.BreakpointRequest:
149		c.errc <- s.handleBreakpoint(req, c.resp.(*protocol.BreakpointResponse))
150	case *protocol.BreakpointAtFunctionRequest:
151		c.errc <- s.handleBreakpointAtFunction(req, c.resp.(*protocol.BreakpointResponse))
152	case *protocol.BreakpointAtLineRequest:
153		c.errc <- s.handleBreakpointAtLine(req, c.resp.(*protocol.BreakpointResponse))
154	case *protocol.DeleteBreakpointsRequest:
155		c.errc <- s.handleDeleteBreakpoints(req, c.resp.(*protocol.DeleteBreakpointsResponse))
156	case *protocol.CloseRequest:
157		c.errc <- s.handleClose(req, c.resp.(*protocol.CloseResponse))
158	case *protocol.EvalRequest:
159		c.errc <- s.handleEval(req, c.resp.(*protocol.EvalResponse))
160	case *protocol.EvaluateRequest:
161		c.errc <- s.handleEvaluate(req, c.resp.(*protocol.EvaluateResponse))
162	case *protocol.FramesRequest:
163		c.errc <- s.handleFrames(req, c.resp.(*protocol.FramesResponse))
164	case *protocol.OpenRequest:
165		c.errc <- s.handleOpen(req, c.resp.(*protocol.OpenResponse))
166	case *protocol.ReadAtRequest:
167		c.errc <- s.handleReadAt(req, c.resp.(*protocol.ReadAtResponse))
168	case *protocol.ResumeRequest:
169		c.errc <- s.handleResume(req, c.resp.(*protocol.ResumeResponse))
170	case *protocol.RunRequest:
171		c.errc <- s.handleRun(req, c.resp.(*protocol.RunResponse))
172	case *protocol.VarByNameRequest:
173		c.errc <- s.handleVarByName(req, c.resp.(*protocol.VarByNameResponse))
174	case *protocol.ValueRequest:
175		c.errc <- s.handleValue(req, c.resp.(*protocol.ValueResponse))
176	case *protocol.MapElementRequest:
177		c.errc <- s.handleMapElement(req, c.resp.(*protocol.MapElementResponse))
178	case *protocol.GoroutinesRequest:
179		c.errc <- s.handleGoroutines(req, c.resp.(*protocol.GoroutinesResponse))
180	default:
181		panic(fmt.Sprintf("unexpected call request type %T", c.req))
182	}
183}
184
185func (s *Server) call(c chan call, req, resp interface{}) error {
186	errc := make(chan error)
187	c <- call{req, resp, errc}
188	return <-errc
189}
190
191type file struct {
192	mode  string
193	index int
194	f     debug.File
195}
196
197func (s *Server) Open(req *protocol.OpenRequest, resp *protocol.OpenResponse) error {
198	return s.call(s.otherc, req, resp)
199}
200
201func (s *Server) handleOpen(req *protocol.OpenRequest, resp *protocol.OpenResponse) error {
202	// TODO: Better simulation. For now we just open the named OS file.
203	var flag int
204	switch req.Mode {
205	case "r":
206		flag = os.O_RDONLY
207	case "w":
208		flag = os.O_WRONLY
209	case "rw":
210		flag = os.O_RDWR
211	default:
212		return fmt.Errorf("Open: bad open mode %q", req.Mode)
213	}
214	osFile, err := os.OpenFile(req.Name, flag, 0)
215	if err != nil {
216		return err
217	}
218	// Find a file descriptor (index) slot.
219	index := 0
220	for ; index < len(s.files) && s.files[index] != nil; index++ {
221	}
222	f := &file{
223		mode:  req.Mode,
224		index: index,
225		f:     osFile,
226	}
227	if index == len(s.files) {
228		s.files = append(s.files, f)
229	} else {
230		s.files[index] = f
231	}
232	return nil
233}
234
235func (s *Server) ReadAt(req *protocol.ReadAtRequest, resp *protocol.ReadAtResponse) error {
236	return s.call(s.otherc, req, resp)
237}
238
239func (s *Server) handleReadAt(req *protocol.ReadAtRequest, resp *protocol.ReadAtResponse) error {
240	fd := req.FD
241	if fd < 0 || len(s.files) <= fd || s.files[fd] == nil {
242		return fmt.Errorf("ReadAt: bad file descriptor %d", fd)
243	}
244	f := s.files[fd]
245	buf := make([]byte, req.Len) // TODO: Don't allocate every time
246	n, err := f.f.ReadAt(buf, req.Offset)
247	resp.Data = buf[:n]
248	return err
249}
250
251func (s *Server) Close(req *protocol.CloseRequest, resp *protocol.CloseResponse) error {
252	return s.call(s.otherc, req, resp)
253}
254
255func (s *Server) handleClose(req *protocol.CloseRequest, resp *protocol.CloseResponse) error {
256	fd := req.FD
257	if fd < 0 || fd >= len(s.files) || s.files[fd] == nil {
258		return fmt.Errorf("Close: bad file descriptor %d", fd)
259	}
260	err := s.files[fd].f.Close()
261	// Remove it regardless
262	s.files[fd] = nil
263	return err
264}
265
266func (s *Server) Run(req *protocol.RunRequest, resp *protocol.RunResponse) error {
267	return s.call(s.otherc, req, resp)
268}
269
270func (s *Server) handleRun(req *protocol.RunRequest, resp *protocol.RunResponse) error {
271	if s.proc != nil {
272		s.proc.Kill()
273		s.proc = nil
274		s.procIsUp = false
275		s.stoppedPid = 0
276		s.stoppedRegs = syscall.PtraceRegs{}
277		s.topOfStackAddrs = nil
278	}
279	argv := append([]string{s.executable}, req.Args...)
280	p, err := s.startProcess(s.executable, argv, &os.ProcAttr{
281		Files: []*os.File{
282			nil,       // TODO: be able to feed the target's stdin.
283			os.Stderr, // TODO: be able to capture the target's stdout.
284			os.Stderr,
285		},
286		Sys: &syscall.SysProcAttr{
287			Pdeathsig: syscall.SIGKILL,
288			Ptrace:    true,
289		},
290	})
291	if err != nil {
292		return err
293	}
294	s.proc = p
295	s.stoppedPid = p.Pid
296	return nil
297}
298
299func (s *Server) Resume(req *protocol.ResumeRequest, resp *protocol.ResumeResponse) error {
300	return s.call(s.otherc, req, resp)
301}
302
303func (s *Server) handleResume(req *protocol.ResumeRequest, resp *protocol.ResumeResponse) error {
304	if s.proc == nil {
305		return fmt.Errorf("Resume: Run did not successfully start a process")
306	}
307
308	if !s.procIsUp {
309		s.procIsUp = true
310		if _, err := s.waitForTrap(s.stoppedPid, false); err != nil {
311			return err
312		}
313		if err := s.ptraceSetOptions(s.stoppedPid, syscall.PTRACE_O_TRACECLONE); err != nil {
314			return fmt.Errorf("ptraceSetOptions: %v", err)
315		}
316	} else if _, ok := s.breakpoints[s.stoppedRegs.Rip]; ok {
317		if err := s.ptraceSingleStep(s.stoppedPid); err != nil {
318			return fmt.Errorf("ptraceSingleStep: %v", err)
319		}
320		if _, err := s.waitForTrap(s.stoppedPid, false); err != nil {
321			return err
322		}
323	}
324
325	for {
326		if err := s.setBreakpoints(); err != nil {
327			return err
328		}
329		if err := s.ptraceCont(s.stoppedPid, 0); err != nil {
330			return fmt.Errorf("ptraceCont: %v", err)
331		}
332
333		wpid, err := s.waitForTrap(-1, true)
334		if err == nil {
335			s.stoppedPid = wpid
336			break
337		}
338		bce, ok := err.(*breakpointsChangedError)
339		if !ok {
340			return err
341		}
342
343		if err := syscall.Kill(s.stoppedPid, syscall.SIGSTOP); err != nil {
344			return fmt.Errorf("kill(SIGSTOP): %v", err)
345		}
346		_, status, err := s.wait(s.stoppedPid, false)
347		if err != nil {
348			return fmt.Errorf("wait (after SIGSTOP): %v", err)
349		}
350		if !status.Stopped() || status.StopSignal() != syscall.SIGSTOP {
351			return fmt.Errorf("wait (after SIGSTOP): unexpected wait status 0x%x", status)
352		}
353
354		if err := s.liftBreakpoints(); err != nil {
355			return err
356		}
357
358	loop:
359		for c := bce.call; ; {
360			s.dispatch(c)
361			select {
362			case c = <-s.breakpointc:
363			default:
364				break loop
365			}
366		}
367	}
368	if err := s.liftBreakpoints(); err != nil {
369		return err
370	}
371
372	if err := s.ptraceGetRegs(s.stoppedPid, &s.stoppedRegs); err != nil {
373		return fmt.Errorf("ptraceGetRegs: %v", err)
374	}
375
376	s.stoppedRegs.Rip -= uint64(s.arch.BreakpointSize)
377
378	if err := s.ptraceSetRegs(s.stoppedPid, &s.stoppedRegs); err != nil {
379		return fmt.Errorf("ptraceSetRegs: %v", err)
380	}
381
382	resp.Status.PC = s.stoppedRegs.Rip
383	resp.Status.SP = s.stoppedRegs.Rsp
384	return nil
385}
386
387func (s *Server) waitForTrap(pid int, allowBreakpointsChange bool) (wpid int, err error) {
388	for {
389		wpid, status, err := s.wait(pid, allowBreakpointsChange)
390		if err != nil {
391			if _, ok := err.(*breakpointsChangedError); !ok {
392				err = fmt.Errorf("wait: %v", err)
393			}
394			return 0, err
395		}
396		if status.StopSignal() == syscall.SIGTRAP && status.TrapCause() != syscall.PTRACE_EVENT_CLONE {
397			return wpid, nil
398		}
399		if status.StopSignal() == syscall.SIGPROF {
400			err = s.ptraceCont(wpid, int(syscall.SIGPROF))
401		} else {
402			err = s.ptraceCont(wpid, 0) // TODO: non-zero when wait catches other signals?
403		}
404		if err != nil {
405			return 0, fmt.Errorf("ptraceCont: %v", err)
406		}
407	}
408}
409
410func (s *Server) Breakpoint(req *protocol.BreakpointRequest, resp *protocol.BreakpointResponse) error {
411	return s.call(s.breakpointc, req, resp)
412}
413
414func (s *Server) handleBreakpoint(req *protocol.BreakpointRequest, resp *protocol.BreakpointResponse) error {
415	return s.addBreakpoints([]uint64{req.Address}, resp)
416}
417
418func (s *Server) BreakpointAtFunction(req *protocol.BreakpointAtFunctionRequest, resp *protocol.BreakpointResponse) error {
419	return s.call(s.breakpointc, req, resp)
420}
421
422func (s *Server) handleBreakpointAtFunction(req *protocol.BreakpointAtFunctionRequest, resp *protocol.BreakpointResponse) error {
423	pc, err := s.functionStartAddress(req.Function)
424	if err != nil {
425		return err
426	}
427	return s.addBreakpoints([]uint64{pc}, resp)
428}
429
430func (s *Server) BreakpointAtLine(req *protocol.BreakpointAtLineRequest, resp *protocol.BreakpointResponse) error {
431	return s.call(s.breakpointc, req, resp)
432}
433
434func (s *Server) handleBreakpointAtLine(req *protocol.BreakpointAtLineRequest, resp *protocol.BreakpointResponse) error {
435	if s.dwarfData == nil {
436		return fmt.Errorf("no DWARF data")
437	}
438	if pcs, err := s.dwarfData.LineToBreakpointPCs(req.File, req.Line); err != nil {
439		return err
440	} else {
441		return s.addBreakpoints(pcs, resp)
442	}
443}
444
445// addBreakpoints adds breakpoints at the addresses in pcs, then stores pcs in the response.
446func (s *Server) addBreakpoints(pcs []uint64, resp *protocol.BreakpointResponse) error {
447	// Get the original code at each address with ptracePeek.
448	bps := make([]breakpoint, 0, len(pcs))
449	for _, pc := range pcs {
450		if _, alreadySet := s.breakpoints[pc]; alreadySet {
451			continue
452		}
453		var bp breakpoint
454		if err := s.ptracePeek(s.stoppedPid, uintptr(pc), bp.origInstr[:s.arch.BreakpointSize]); err != nil {
455			return fmt.Errorf("ptracePeek: %v", err)
456		}
457		bp.pc = pc
458		bps = append(bps, bp)
459	}
460	// If all the peeks succeeded, update the list of breakpoints.
461	for _, bp := range bps {
462		s.breakpoints[bp.pc] = bp
463	}
464	resp.PCs = pcs
465	return nil
466}
467
468func (s *Server) DeleteBreakpoints(req *protocol.DeleteBreakpointsRequest, resp *protocol.DeleteBreakpointsResponse) error {
469	return s.call(s.breakpointc, req, resp)
470}
471
472func (s *Server) handleDeleteBreakpoints(req *protocol.DeleteBreakpointsRequest, resp *protocol.DeleteBreakpointsResponse) error {
473	for _, pc := range req.PCs {
474		delete(s.breakpoints, pc)
475	}
476	return nil
477}
478
479func (s *Server) setBreakpoints() error {
480	for pc := range s.breakpoints {
481		err := s.ptracePoke(s.stoppedPid, uintptr(pc), s.arch.BreakpointInstr[:s.arch.BreakpointSize])
482		if err != nil {
483			return fmt.Errorf("setBreakpoints: %v", err)
484		}
485	}
486	return nil
487}
488
489func (s *Server) liftBreakpoints() error {
490	for pc, breakpoint := range s.breakpoints {
491		err := s.ptracePoke(s.stoppedPid, uintptr(pc), breakpoint.origInstr[:s.arch.BreakpointSize])
492		if err != nil {
493			return fmt.Errorf("liftBreakpoints: %v", err)
494		}
495	}
496	return nil
497}
498
499func (s *Server) Eval(req *protocol.EvalRequest, resp *protocol.EvalResponse) error {
500	return s.call(s.otherc, req, resp)
501}
502
503func (s *Server) handleEval(req *protocol.EvalRequest, resp *protocol.EvalResponse) (err error) {
504	resp.Result, err = s.eval(req.Expr)
505	return err
506}
507
508// eval evaluates an expression.
509// TODO: very weak.
510func (s *Server) eval(expr string) ([]string, error) {
511	switch {
512	case strings.HasPrefix(expr, "re:"):
513		// Regular expression. Return list of symbols.
514		re, err := regexp.Compile(expr[3:])
515		if err != nil {
516			return nil, err
517		}
518		return s.dwarfData.LookupMatchingSymbols(re)
519
520	case strings.HasPrefix(expr, "addr:"):
521		// Symbol lookup. Return address.
522		addr, err := s.functionStartAddress(expr[5:])
523		if err != nil {
524			return nil, err
525		}
526		return []string{fmt.Sprintf("%#x", addr)}, nil
527
528	case strings.HasPrefix(expr, "val:"):
529		// Symbol lookup. Return formatted value.
530		value, err := s.printer.Sprint(expr[4:])
531		if err != nil {
532			return nil, err
533		}
534		return []string{value}, nil
535
536	case strings.HasPrefix(expr, "src:"):
537		// Numerical address. Return file.go:123.
538		addr, err := strconv.ParseUint(expr[4:], 0, 0)
539		if err != nil {
540			return nil, err
541		}
542		file, line, err := s.lookupSource(addr)
543		if err != nil {
544			return nil, err
545		}
546		return []string{fmt.Sprintf("%s:%d", file, line)}, nil
547
548	case len(expr) > 0 && '0' <= expr[0] && expr[0] <= '9':
549		// Numerical address. Return symbol.
550		addr, err := strconv.ParseUint(expr, 0, 0)
551		if err != nil {
552			return nil, err
553		}
554		entry, _, err := s.dwarfData.PCToFunction(addr)
555		if err != nil {
556			return nil, err
557		}
558		name, ok := entry.Val(dwarf.AttrName).(string)
559		if !ok {
560			return nil, fmt.Errorf("function at 0x%x has no name", addr)
561		}
562		return []string{name}, nil
563	}
564
565	return nil, fmt.Errorf("bad expression syntax: %q", expr)
566}
567
568func (s *Server) Evaluate(req *protocol.EvaluateRequest, resp *protocol.EvaluateResponse) error {
569	return s.call(s.otherc, req, resp)
570}
571
572func (s *Server) handleEvaluate(req *protocol.EvaluateRequest, resp *protocol.EvaluateResponse) (err error) {
573	resp.Result, err = s.evalExpression(req.Expression, s.stoppedRegs.Rip, s.stoppedRegs.Rsp)
574	return err
575}
576
577func (s *Server) lookupSource(pc uint64) (file string, line uint64, err error) {
578	if s.dwarfData == nil {
579		return
580	}
581	// TODO: The gosym equivalent also returns the relevant Func. Do that when
582	// DWARF has the same facility.
583	return s.dwarfData.PCToLine(pc)
584}
585
586func (s *Server) Frames(req *protocol.FramesRequest, resp *protocol.FramesResponse) error {
587	return s.call(s.otherc, req, resp)
588}
589
590func (s *Server) handleFrames(req *protocol.FramesRequest, resp *protocol.FramesResponse) error {
591	// TODO: verify that we're stopped.
592	if s.topOfStackAddrs == nil {
593		if err := s.evaluateTopOfStackAddrs(); err != nil {
594			return err
595		}
596	}
597
598	regs := syscall.PtraceRegs{}
599	err := s.ptraceGetRegs(s.stoppedPid, &regs)
600	if err != nil {
601		return err
602	}
603	resp.Frames, err = s.walkStack(regs.Rip, regs.Rsp, req.Count)
604	return err
605}
606
607// walkStack returns up to the requested number of stack frames.
608func (s *Server) walkStack(pc, sp uint64, count int) ([]debug.Frame, error) {
609	var frames []debug.Frame
610
611	var buf [8]byte
612	b := new(bytes.Buffer)
613	r := s.dwarfData.Reader()
614
615	// TODO: handle walking over a split stack.
616	for i := 0; i < count; i++ {
617		b.Reset()
618		file, line, err := s.dwarfData.PCToLine(pc)
619		if err != nil {
620			return frames, err
621		}
622		fpOffset, err := s.dwarfData.PCToSPOffset(pc)
623		if err != nil {
624			return frames, err
625		}
626		fp := sp + uint64(fpOffset)
627		entry, funcEntry, err := s.dwarfData.PCToFunction(pc)
628		if err != nil {
629			return frames, err
630		}
631		frame := debug.Frame{
632			PC:            pc,
633			SP:            sp,
634			File:          file,
635			Line:          line,
636			FunctionStart: funcEntry,
637		}
638		frame.Function, _ = entry.Val(dwarf.AttrName).(string)
639		r.Seek(entry.Offset)
640		for {
641			entry, err := r.Next()
642			if err != nil {
643				return frames, err
644			}
645			if entry.Tag == 0 {
646				break
647			}
648			// TODO: report variables we couldn't parse?
649			if entry.Tag == dwarf.TagFormalParameter {
650				if v, err := s.parseParameterOrLocal(entry, fp); err == nil {
651					frame.Params = append(frame.Params, debug.Param(v))
652				}
653			}
654			if entry.Tag == dwarf.TagVariable {
655				if v, err := s.parseParameterOrLocal(entry, fp); err == nil {
656					frame.Vars = append(frame.Vars, v)
657				}
658			}
659		}
660		frames = append(frames, frame)
661
662		// Walk to the caller's PC and SP.
663		if s.topOfStack(funcEntry) {
664			break
665		}
666		err = s.ptracePeek(s.stoppedPid, uintptr(fp-uint64(s.arch.PointerSize)), buf[:s.arch.PointerSize])
667		if err != nil {
668			return frames, fmt.Errorf("ptracePeek: %v", err)
669		}
670		pc, sp = s.arch.Uintptr(buf[:s.arch.PointerSize]), fp
671	}
672	return frames, nil
673}
674
675// parseParameterOrLocal parses the entry for a function parameter or local
676// variable, which are both specified the same way. fp contains the frame
677// pointer, which is used to calculate the variable location.
678func (s *Server) parseParameterOrLocal(entry *dwarf.Entry, fp uint64) (debug.LocalVar, error) {
679	var v debug.LocalVar
680	v.Name, _ = entry.Val(dwarf.AttrName).(string)
681	if off, err := s.dwarfData.EntryTypeOffset(entry); err != nil {
682		return v, err
683	} else {
684		v.Var.TypeID = uint64(off)
685	}
686	if i := entry.Val(dwarf.AttrLocation); i == nil {
687		return v, fmt.Errorf("missing location description")
688	} else if locationDescription, ok := i.([]uint8); !ok {
689		return v, fmt.Errorf("unsupported location description")
690	} else if offset, err := evalLocation(locationDescription); err != nil {
691		return v, err
692	} else {
693		v.Var.Address = fp + uint64(offset)
694	}
695	return v, nil
696}
697
698func (s *Server) evaluateTopOfStackAddrs() error {
699	var (
700		lookup   func(name string) (uint64, error)
701		indirect bool
702		names    []string
703	)
704	if _, err := s.dwarfData.LookupVariable("runtime.rt0_goPC"); err != nil {
705		// Look for a Go 1.3 binary (or earlier version).
706		lookup, indirect, names = s.functionStartAddress, false, []string{
707			"runtime.goexit",
708			"runtime.mstart",
709			"runtime.mcall",
710			"runtime.morestack",
711			"runtime.lessstack",
712			"_rt0_go",
713		}
714	} else {
715		// Look for a Go 1.4 binary (or later version).
716		lookup = func(name string) (uint64, error) {
717			entry, err := s.dwarfData.LookupVariable(name)
718			if err != nil {
719				return 0, err
720			}
721			return s.dwarfData.EntryLocation(entry)
722		}
723		indirect, names = true, []string{
724			"runtime.goexitPC",
725			"runtime.mstartPC",
726			"runtime.mcallPC",
727			"runtime.morestackPC",
728			"runtime.rt0_goPC",
729		}
730	}
731	// TODO: also look for runtime.externalthreadhandlerp, on Windows.
732
733	addrs := make([]uint64, 0, len(names))
734	for _, name := range names {
735		addr, err := lookup(name)
736		if err != nil {
737			return err
738		}
739		addrs = append(addrs, addr)
740	}
741
742	if indirect {
743		buf := make([]byte, s.arch.PointerSize)
744		for i, addr := range addrs {
745			if err := s.ptracePeek(s.stoppedPid, uintptr(addr), buf); err != nil {
746				return fmt.Errorf("ptracePeek: %v", err)
747			}
748			addrs[i] = s.arch.Uintptr(buf)
749		}
750	}
751
752	s.topOfStackAddrs = addrs
753	return nil
754}
755
756// topOfStack is the out-of-process equivalent of runtime·topofstack.
757func (s *Server) topOfStack(funcEntry uint64) bool {
758	for _, addr := range s.topOfStackAddrs {
759		if addr == funcEntry {
760			return true
761		}
762	}
763	return false
764}
765
766func (s *Server) VarByName(req *protocol.VarByNameRequest, resp *protocol.VarByNameResponse) error {
767	return s.call(s.otherc, req, resp)
768}
769
770func (s *Server) handleVarByName(req *protocol.VarByNameRequest, resp *protocol.VarByNameResponse) error {
771	entry, err := s.dwarfData.LookupVariable(req.Name)
772	if err != nil {
773		return fmt.Errorf("variable %s: %s", req.Name, err)
774	}
775
776	loc, err := s.dwarfData.EntryLocation(entry)
777	if err != nil {
778		return fmt.Errorf("variable %s: %s", req.Name, err)
779	}
780
781	off, err := s.dwarfData.EntryTypeOffset(entry)
782	if err != nil {
783		return fmt.Errorf("variable %s: %s", req.Name, err)
784	}
785
786	resp.Var.TypeID = uint64(off)
787	resp.Var.Address = loc
788	return nil
789}
790
791func (s *Server) Value(req *protocol.ValueRequest, resp *protocol.ValueResponse) error {
792	return s.call(s.otherc, req, resp)
793}
794
795func (s *Server) handleValue(req *protocol.ValueRequest, resp *protocol.ValueResponse) error {
796	t, err := s.dwarfData.Type(dwarf.Offset(req.Var.TypeID))
797	if err != nil {
798		return err
799	}
800	resp.Value, err = s.value(t, req.Var.Address)
801	return err
802}
803
804func (s *Server) MapElement(req *protocol.MapElementRequest, resp *protocol.MapElementResponse) error {
805	return s.call(s.otherc, req, resp)
806}
807
808func (s *Server) handleMapElement(req *protocol.MapElementRequest, resp *protocol.MapElementResponse) error {
809	t, err := s.dwarfData.Type(dwarf.Offset(req.Map.TypeID))
810	if err != nil {
811		return err
812	}
813	m, ok := t.(*dwarf.MapType)
814	if !ok {
815		return fmt.Errorf("variable is not a map")
816	}
817	var count uint64
818	// fn will be called for each element of the map.
819	// When we reach the requested element, we fill in *resp and stop.
820	// TODO: cache locations of elements.
821	fn := func(keyAddr, valAddr uint64, keyType, valType dwarf.Type) bool {
822		count++
823		if count == req.Index+1 {
824			resp.Key = debug.Var{TypeID: uint64(keyType.Common().Offset), Address: keyAddr}
825			resp.Value = debug.Var{TypeID: uint64(valType.Common().Offset), Address: valAddr}
826			return false
827		}
828		return true
829	}
830	if err := s.peekMapValues(m, req.Map.Address, fn); err != nil {
831		return err
832	}
833	if count <= req.Index {
834		// There weren't enough elements.
835		return fmt.Errorf("map has no element %d", req.Index)
836	}
837	return nil
838}
839
840func (s *Server) Goroutines(req *protocol.GoroutinesRequest, resp *protocol.GoroutinesResponse) error {
841	return s.call(s.otherc, req, resp)
842}
843
844const invalidStatus debug.GoroutineStatus = 99
845
846var (
847	gStatus = [...]debug.GoroutineStatus{
848		0: debug.Queued,  // _Gidle
849		1: debug.Queued,  // _Grunnable
850		2: debug.Running, // _Grunning
851		3: debug.Blocked, // _Gsyscall
852		4: debug.Blocked, // _Gwaiting
853		5: invalidStatus, // _Gmoribund_unused
854		6: invalidStatus, // _Gdead
855		7: invalidStatus, // _Genqueue
856		8: debug.Running, // _Gcopystack
857	}
858	gScanStatus = [...]debug.GoroutineStatus{
859		0: invalidStatus, // _Gscan + _Gidle
860		1: debug.Queued,  // _Gscanrunnable
861		2: debug.Running, // _Gscanrunning
862		3: debug.Blocked, // _Gscansyscall
863		4: debug.Blocked, // _Gscanwaiting
864		5: invalidStatus, // _Gscan + _Gmoribund_unused
865		6: invalidStatus, // _Gscan + _Gdead
866		7: debug.Queued,  // _Gscanenqueue
867	}
868	gStatusString = [...]string{
869		0: "idle",
870		1: "runnable",
871		2: "running",
872		3: "syscall",
873		4: "waiting",
874		8: "copystack",
875	}
876	gScanStatusString = [...]string{
877		1: "scanrunnable",
878		2: "scanrunning",
879		3: "scansyscall",
880		4: "scanwaiting",
881		7: "scanenqueue",
882	}
883)
884
885func (s *Server) handleGoroutines(req *protocol.GoroutinesRequest, resp *protocol.GoroutinesResponse) error {
886	// Get DWARF type information for runtime.g.
887	ge, err := s.dwarfData.LookupEntry("runtime.g")
888	if err != nil {
889		return err
890	}
891	t, err := s.dwarfData.Type(ge.Offset)
892	if err != nil {
893		return err
894	}
895	gType, ok := followTypedefs(t).(*dwarf.StructType)
896	if !ok {
897		return errors.New("runtime.g is not a struct")
898	}
899
900	var (
901		allgPtr, allgLen uint64
902		allgPtrOk        bool
903	)
904	for {
905		// Try to read the slice runtime.allgs.
906		allgsEntry, err := s.dwarfData.LookupVariable("runtime.allgs")
907		if err != nil {
908			break
909		}
910		allgsAddr, err := s.dwarfData.EntryLocation(allgsEntry)
911		if err != nil {
912			break
913		}
914		off, err := s.dwarfData.EntryTypeOffset(allgsEntry)
915		if err != nil {
916			break
917		}
918		t, err := s.dwarfData.Type(off)
919		if err != nil {
920			break
921		}
922		allgsType, ok := followTypedefs(t).(*dwarf.SliceType)
923		if !ok {
924			break
925		}
926		allgs, err := s.peekSlice(allgsType, allgsAddr)
927		if err != nil {
928			break
929		}
930
931		allgPtr, allgLen, allgPtrOk = allgs.Address, allgs.Length, true
932		break
933	}
934	if !allgPtrOk {
935		// Read runtime.allg.
936		allgEntry, err := s.dwarfData.LookupVariable("runtime.allg")
937		if err != nil {
938			return err
939		}
940		allgAddr, err := s.dwarfData.EntryLocation(allgEntry)
941		if err != nil {
942			return err
943		}
944		allgPtr, err = s.peekPtr(allgAddr)
945		if err != nil {
946			return fmt.Errorf("reading allg: %v", err)
947		}
948
949		// Read runtime.allglen.
950		allglenEntry, err := s.dwarfData.LookupVariable("runtime.allglen")
951		if err != nil {
952			return err
953		}
954		off, err := s.dwarfData.EntryTypeOffset(allglenEntry)
955		if err != nil {
956			return err
957		}
958		allglenType, err := s.dwarfData.Type(off)
959		if err != nil {
960			return err
961		}
962		allglenAddr, err := s.dwarfData.EntryLocation(allglenEntry)
963		if err != nil {
964			return err
965		}
966		switch followTypedefs(allglenType).(type) {
967		case *dwarf.UintType, *dwarf.IntType:
968			allgLen, err = s.peekUint(allglenAddr, allglenType.Common().ByteSize)
969			if err != nil {
970				return fmt.Errorf("reading allglen: %v", err)
971			}
972		default:
973			// Some runtimes don't specify the type for allglen.  Assume it's uint32.
974			allgLen, err = s.peekUint(allglenAddr, 4)
975			if err != nil {
976				return fmt.Errorf("reading allglen: %v", err)
977			}
978			if allgLen != 0 {
979				break
980			}
981			// Zero?  Let's try uint64.
982			allgLen, err = s.peekUint(allglenAddr, 8)
983			if err != nil {
984				return fmt.Errorf("reading allglen: %v", err)
985			}
986		}
987	}
988
989	// Initialize s.goroutineStack.
990	s.goroutineStackOnce.Do(func() { s.goroutineStackInit(gType) })
991
992	for i := uint64(0); i < allgLen; i++ {
993		// allg is an array of pointers to g structs.  Read allg[i].
994		g, err := s.peekPtr(allgPtr + i*uint64(s.arch.PointerSize))
995		if err != nil {
996			return err
997		}
998		gr := debug.Goroutine{}
999
1000		// Read status from the field named "atomicstatus" or "status".
1001		status, err := s.peekUintStructField(gType, g, "atomicstatus")
1002		if err != nil {
1003			status, err = s.peekUintOrIntStructField(gType, g, "status")
1004		}
1005		if err != nil {
1006			return err
1007		}
1008		if status == 6 {
1009			// _Gdead.
1010			continue
1011		}
1012		gr.Status = invalidStatus
1013		if status < uint64(len(gStatus)) {
1014			gr.Status = gStatus[status]
1015			gr.StatusString = gStatusString[status]
1016		} else if status^0x1000 < uint64(len(gScanStatus)) {
1017			gr.Status = gScanStatus[status^0x1000]
1018			gr.StatusString = gScanStatusString[status^0x1000]
1019		}
1020		if gr.Status == invalidStatus {
1021			return fmt.Errorf("unexpected goroutine status 0x%x", status)
1022		}
1023		if status == 4 || status == 0x1004 {
1024			// _Gwaiting or _Gscanwaiting.
1025			// Try reading waitreason to get a better value for StatusString.
1026			// Depending on the runtime, waitreason may be a Go string or a C string.
1027			if waitreason, err := s.peekStringStructField(gType, g, "waitreason", 80); err == nil {
1028				if waitreason != "" {
1029					gr.StatusString = waitreason
1030				}
1031			} else if ptr, err := s.peekPtrStructField(gType, g, "waitreason"); err == nil {
1032				waitreason := s.peekCString(ptr, 80)
1033				if waitreason != "" {
1034					gr.StatusString = waitreason
1035				}
1036			}
1037		}
1038
1039		gr.ID, err = s.peekIntStructField(gType, g, "goid")
1040		if err != nil {
1041			return err
1042		}
1043
1044		// Best-effort attempt to get the names of the goroutine function and the
1045		// function that created the goroutine.  They aren't always available.
1046		functionName := func(pc uint64) string {
1047			entry, _, err := s.dwarfData.PCToFunction(pc)
1048			if err != nil {
1049				return ""
1050			}
1051			name, _ := entry.Val(dwarf.AttrName).(string)
1052			return name
1053		}
1054		if startpc, err := s.peekUintStructField(gType, g, "startpc"); err == nil {
1055			gr.Function = functionName(startpc)
1056		}
1057		if gopc, err := s.peekUintStructField(gType, g, "gopc"); err == nil {
1058			gr.Caller = functionName(gopc)
1059		}
1060		if gr.Status != debug.Running {
1061			// TODO: running goroutines too.
1062			gr.StackFrames, _ = s.goroutineStack(g)
1063		}
1064
1065		resp.Goroutines = append(resp.Goroutines, &gr)
1066	}
1067
1068	return nil
1069}
1070
1071// TODO: let users specify how many frames they want.  10 will be enough to
1072// determine the reason a goroutine is blocked.
1073const goroutineStackFrameCount = 10
1074
1075// goroutineStackInit initializes s.goroutineStack.
1076func (s *Server) goroutineStackInit(gType *dwarf.StructType) {
1077	// If we fail to read the DWARF data needed for s.goroutineStack, calling it
1078	// will always return the error that occurred during initialization.
1079	var err error // err is captured by the func below.
1080	s.goroutineStack = func(gAddr uint64) ([]debug.Frame, error) {
1081		return nil, err
1082	}
1083
1084	// Get g field "sched", which contains fields pc and sp.
1085	schedField, err := getField(gType, "sched")
1086	if err != nil {
1087		return
1088	}
1089	schedOffset := uint64(schedField.ByteOffset)
1090	schedType, ok := followTypedefs(schedField.Type).(*dwarf.StructType)
1091	if !ok {
1092		err = errors.New(`g field "sched" has the wrong type`)
1093		return
1094	}
1095
1096	// Get the size of the pc and sp fields and their offsets inside the g struct,
1097	// so we can quickly peek those values for each goroutine later.
1098	var (
1099		schedPCOffset, schedSPOffset     uint64
1100		schedPCByteSize, schedSPByteSize int64
1101	)
1102	for _, x := range []struct {
1103		field    string
1104		offset   *uint64
1105		bytesize *int64
1106	}{
1107		{"pc", &schedPCOffset, &schedPCByteSize},
1108		{"sp", &schedSPOffset, &schedSPByteSize},
1109	} {
1110		var f *dwarf.StructField
1111		f, err = getField(schedType, x.field)
1112		if err != nil {
1113			return
1114		}
1115		*x.offset = schedOffset + uint64(f.ByteOffset)
1116		switch t := followTypedefs(f.Type).(type) {
1117		case *dwarf.UintType, *dwarf.IntType:
1118			*x.bytesize = t.Common().ByteSize
1119		default:
1120			err = fmt.Errorf("gobuf field %q has the wrong type", x.field)
1121			return
1122		}
1123	}
1124
1125	s.goroutineStack = func(gAddr uint64) ([]debug.Frame, error) {
1126		schedPC, err := s.peekUint(gAddr+schedPCOffset, schedPCByteSize)
1127		if err != nil {
1128			return nil, err
1129		}
1130		schedSP, err := s.peekUint(gAddr+schedSPOffset, schedSPByteSize)
1131		if err != nil {
1132			return nil, err
1133		}
1134		return s.walkStack(schedPC, schedSP, goroutineStackFrameCount)
1135	}
1136}
1137