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 }