github.com/undoio/delve@v1.9.0/pkg/proc/core/delve_core.go (about)

     1  package core
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/undoio/delve/pkg/dwarf/op"
    11  	"github.com/undoio/delve/pkg/elfwriter"
    12  	"github.com/undoio/delve/pkg/proc"
    13  )
    14  
    15  func platformFromNotes(notes []*note) (goos, goarch string, err error) {
    16  	for _, note := range notes {
    17  		if note.Type != elfwriter.DelveHeaderNoteType {
    18  			continue
    19  		}
    20  		lines := strings.Split(string(note.Desc.([]byte)), "\n")
    21  		v := strings.Split(lines[0], "/")
    22  		if len(v) != 2 {
    23  			return "", "", fmt.Errorf("malformed delve header note: %q", string(note.Desc.([]byte)))
    24  		}
    25  		return v[0], v[1], nil
    26  	}
    27  	panic("internal error")
    28  }
    29  
    30  func threadsFromDelveNotes(p *process, notes []*note) (proc.Thread, error) {
    31  	var currentThread proc.Thread
    32  	for _, note := range notes {
    33  		if note.Type == elfwriter.DelveHeaderNoteType {
    34  			buf := bytes.NewBuffer(note.Desc.([]byte))
    35  			for {
    36  				line, err := buf.ReadString('\n')
    37  				if err != nil {
    38  					break
    39  				}
    40  				if len(line) > 0 && line[len(line)-1] == '\n' {
    41  					line = line[:len(line)-1]
    42  				}
    43  				switch {
    44  				case strings.HasPrefix(line, elfwriter.DelveHeaderTargetPidPrefix):
    45  					pid, err := strconv.ParseUint(line[len(elfwriter.DelveHeaderTargetPidPrefix):], 10, 64)
    46  					if err != nil {
    47  						return nil, fmt.Errorf("malformed delve header note (bad pid): %v", err)
    48  					}
    49  					p.pid = int(pid)
    50  				case strings.HasPrefix(line, elfwriter.DelveHeaderEntryPointPrefix):
    51  					entry, err := strconv.ParseUint(line[len(elfwriter.DelveHeaderEntryPointPrefix):], 0, 64)
    52  					if err != nil {
    53  						return nil, fmt.Errorf("malformed delve header note (bad entry point): %v", err)
    54  					}
    55  					p.entryPoint = entry
    56  				}
    57  			}
    58  		}
    59  
    60  		if note.Type != elfwriter.DelveThreadNodeType {
    61  			continue
    62  		}
    63  		body := bytes.NewReader(note.Desc.([]byte))
    64  		th := new(delveThread)
    65  		th.regs = new(delveRegisters)
    66  
    67  		var readerr error
    68  		read := func(out interface{}) {
    69  			if readerr != nil {
    70  				return
    71  			}
    72  			readerr = binary.Read(body, binary.LittleEndian, out)
    73  		}
    74  
    75  		read(&th.id)
    76  
    77  		read(&th.regs.pc)
    78  		read(&th.regs.sp)
    79  		read(&th.regs.bp)
    80  		read(&th.regs.tls)
    81  		read(&th.regs.hasGAddr)
    82  		read(&th.regs.gaddr)
    83  
    84  		var n uint32
    85  		read(&n)
    86  
    87  		if readerr != nil {
    88  			return nil, fmt.Errorf("error reading thread note header for thread %d: %v", th.id, readerr)
    89  		}
    90  
    91  		th.regs.slice = make([]proc.Register, n)
    92  
    93  		readBytes := func(maxlen uint16, kind string) []byte {
    94  			if readerr != nil {
    95  				return nil
    96  			}
    97  			var len uint16
    98  			read(&len)
    99  			if maxlen > 0 && len > maxlen {
   100  				readerr = fmt.Errorf("maximum len exceeded (%d) reading %s", len, kind)
   101  				return nil
   102  			}
   103  			buf := make([]byte, len)
   104  			if readerr != nil {
   105  				return nil
   106  			}
   107  			_, readerr = body.Read(buf)
   108  			return buf
   109  		}
   110  
   111  		for i := 0; i < int(n); i++ {
   112  			name := string(readBytes(20, "register name"))
   113  			value := readBytes(2048, "register value")
   114  			th.regs.slice[i] = proc.Register{Name: name, Reg: op.DwarfRegisterFromBytes(value)}
   115  			if readerr != nil {
   116  				return nil, fmt.Errorf("error reading thread note registers for thread %d: %v", th.id, readerr)
   117  			}
   118  		}
   119  
   120  		p.Threads[int(th.id)] = &thread{th, p, proc.CommonThread{}}
   121  		if currentThread == nil {
   122  			currentThread = p.Threads[int(th.id)]
   123  		}
   124  	}
   125  	return currentThread, nil
   126  }
   127  
   128  type delveThread struct {
   129  	id   uint64
   130  	regs *delveRegisters
   131  }
   132  
   133  func (th *delveThread) pid() int {
   134  	return int(th.id)
   135  }
   136  
   137  func (th *delveThread) registers() (proc.Registers, error) {
   138  	return th.regs, nil
   139  }
   140  
   141  type delveRegisters struct {
   142  	pc, sp, bp, tls uint64
   143  	hasGAddr        bool
   144  	gaddr           uint64
   145  	slice           []proc.Register
   146  }
   147  
   148  func (regs *delveRegisters) PC() uint64            { return regs.pc }
   149  func (regs *delveRegisters) BP() uint64            { return regs.bp }
   150  func (regs *delveRegisters) SP() uint64            { return regs.sp }
   151  func (regs *delveRegisters) TLS() uint64           { return regs.tls }
   152  func (regs *delveRegisters) GAddr() (uint64, bool) { return regs.gaddr, regs.hasGAddr }
   153  func (regs *delveRegisters) LR() uint64            { return 0 }
   154  
   155  func (regs *delveRegisters) Copy() (proc.Registers, error) {
   156  	return regs, nil
   157  }
   158  
   159  func (regs *delveRegisters) Slice(bool) ([]proc.Register, error) {
   160  	return regs.slice, nil
   161  }