mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 10:47:27 +08:00 
			
		
		
		
	 35d4f05c4e
			
		
	
	35d4f05c4e
	
	
	
		
			
			Moves the implementation of Registers.Get out of the backends and into proc where it can be implemented only once per architecture.
		
			
				
	
	
		
			161 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package core
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"encoding/binary"
 | |
| 	"fmt"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/go-delve/delve/pkg/dwarf/op"
 | |
| 	"github.com/go-delve/delve/pkg/elfwriter"
 | |
| 	"github.com/go-delve/delve/pkg/proc"
 | |
| )
 | |
| 
 | |
| func platformFromNotes(notes []*note) (goos, goarch string, err error) {
 | |
| 	for _, note := range notes {
 | |
| 		if note.Type != elfwriter.DelveHeaderNoteType {
 | |
| 			continue
 | |
| 		}
 | |
| 		lines := strings.Split(string(note.Desc.([]byte)), "\n")
 | |
| 		v := strings.Split(lines[0], "/")
 | |
| 		if len(v) != 2 {
 | |
| 			return "", "", fmt.Errorf("malformed delve header note: %q", string(note.Desc.([]byte)))
 | |
| 		}
 | |
| 		return v[0], v[1], nil
 | |
| 	}
 | |
| 	panic("internal error")
 | |
| }
 | |
| 
 | |
| func threadsFromDelveNotes(p *process, notes []*note) (proc.Thread, error) {
 | |
| 	var currentThread proc.Thread
 | |
| 	for _, note := range notes {
 | |
| 		if note.Type == elfwriter.DelveHeaderNoteType {
 | |
| 			buf := bytes.NewBuffer(note.Desc.([]byte))
 | |
| 			for {
 | |
| 				line, err := buf.ReadString('\n')
 | |
| 				if err != nil {
 | |
| 					break
 | |
| 				}
 | |
| 				if len(line) > 0 && line[len(line)-1] == '\n' {
 | |
| 					line = line[:len(line)-1]
 | |
| 				}
 | |
| 				switch {
 | |
| 				case strings.HasPrefix(line, elfwriter.DelveHeaderTargetPidPrefix):
 | |
| 					pid, err := strconv.ParseUint(line[len(elfwriter.DelveHeaderTargetPidPrefix):], 10, 64)
 | |
| 					if err != nil {
 | |
| 						return nil, fmt.Errorf("malformed delve header note (bad pid): %v", err)
 | |
| 					}
 | |
| 					p.pid = int(pid)
 | |
| 				case strings.HasPrefix(line, elfwriter.DelveHeaderEntryPointPrefix):
 | |
| 					entry, err := strconv.ParseUint(line[len(elfwriter.DelveHeaderEntryPointPrefix):], 0, 64)
 | |
| 					if err != nil {
 | |
| 						return nil, fmt.Errorf("malformed delve header note (bad entry point): %v", err)
 | |
| 					}
 | |
| 					p.entryPoint = entry
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if note.Type != elfwriter.DelveThreadNodeType {
 | |
| 			continue
 | |
| 		}
 | |
| 		body := bytes.NewReader(note.Desc.([]byte))
 | |
| 		th := new(delveThread)
 | |
| 		th.regs = new(delveRegisters)
 | |
| 
 | |
| 		var readerr error
 | |
| 		read := func(out interface{}) {
 | |
| 			if readerr != nil {
 | |
| 				return
 | |
| 			}
 | |
| 			readerr = binary.Read(body, binary.LittleEndian, out)
 | |
| 		}
 | |
| 
 | |
| 		read(&th.id)
 | |
| 
 | |
| 		read(&th.regs.pc)
 | |
| 		read(&th.regs.sp)
 | |
| 		read(&th.regs.bp)
 | |
| 		read(&th.regs.tls)
 | |
| 		read(&th.regs.hasGAddr)
 | |
| 		read(&th.regs.gaddr)
 | |
| 
 | |
| 		var n uint32
 | |
| 		read(&n)
 | |
| 
 | |
| 		if readerr != nil {
 | |
| 			return nil, fmt.Errorf("error reading thread note header for thread %d: %v", th.id, readerr)
 | |
| 		}
 | |
| 
 | |
| 		th.regs.slice = make([]proc.Register, n)
 | |
| 
 | |
| 		readBytes := func(maxlen uint16, kind string) []byte {
 | |
| 			if readerr != nil {
 | |
| 				return nil
 | |
| 			}
 | |
| 			var len uint16
 | |
| 			read(&len)
 | |
| 			if maxlen > 0 && len > maxlen {
 | |
| 				readerr = fmt.Errorf("maximum len exceeded (%d) reading %s", len, kind)
 | |
| 				return nil
 | |
| 			}
 | |
| 			buf := make([]byte, len)
 | |
| 			if readerr != nil {
 | |
| 				return nil
 | |
| 			}
 | |
| 			_, readerr = body.Read(buf)
 | |
| 			return buf
 | |
| 		}
 | |
| 
 | |
| 		for i := 0; i < int(n); i++ {
 | |
| 			name := string(readBytes(20, "register name"))
 | |
| 			value := readBytes(2048, "register value")
 | |
| 			th.regs.slice[i] = proc.Register{Name: name, Reg: op.DwarfRegisterFromBytes(value)}
 | |
| 			if readerr != nil {
 | |
| 				return nil, fmt.Errorf("error reading thread note registers for thread %d: %v", th.id, readerr)
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		p.Threads[int(th.id)] = &thread{th, p, proc.CommonThread{}}
 | |
| 		if currentThread == nil {
 | |
| 			currentThread = p.Threads[int(th.id)]
 | |
| 		}
 | |
| 	}
 | |
| 	return currentThread, nil
 | |
| }
 | |
| 
 | |
| type delveThread struct {
 | |
| 	id   uint64
 | |
| 	regs *delveRegisters
 | |
| }
 | |
| 
 | |
| func (th *delveThread) pid() int {
 | |
| 	return int(th.id)
 | |
| }
 | |
| 
 | |
| func (th *delveThread) registers() (proc.Registers, error) {
 | |
| 	return th.regs, nil
 | |
| }
 | |
| 
 | |
| type delveRegisters struct {
 | |
| 	pc, sp, bp, tls uint64
 | |
| 	hasGAddr        bool
 | |
| 	gaddr           uint64
 | |
| 	slice           []proc.Register
 | |
| }
 | |
| 
 | |
| func (regs *delveRegisters) PC() uint64            { return regs.pc }
 | |
| func (regs *delveRegisters) BP() uint64            { return regs.bp }
 | |
| func (regs *delveRegisters) SP() uint64            { return regs.sp }
 | |
| func (regs *delveRegisters) TLS() uint64           { return regs.tls }
 | |
| func (regs *delveRegisters) GAddr() (uint64, bool) { return regs.gaddr, regs.hasGAddr }
 | |
| 
 | |
| func (regs *delveRegisters) Copy() (proc.Registers, error) {
 | |
| 	return regs, nil
 | |
| }
 | |
| 
 | |
| func (regs *delveRegisters) Slice(bool) ([]proc.Register, error) {
 | |
| 	return regs.slice, nil
 | |
| }
 |