github.com/cnboonhan/delve@v0.0.0-20230908061759-363f2388c2fb/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/go-delve/delve/pkg/dwarf/op" 11 "github.com/go-delve/delve/pkg/elfwriter" 12 "github.com/go-delve/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 if readerr != nil { 104 return nil 105 } 106 buf := make([]byte, len) 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 }