File: parse_util.go

package info (click to toggle)
delve 1.24.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 14,092 kB
  • sloc: ansic: 111,943; sh: 169; asm: 141; makefile: 43; python: 23
file content (193 lines) | stat: -rw-r--r-- 4,076 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
package line

import (
	"bytes"
	"encoding/binary"
	"errors"

	"github.com/go-delve/delve/pkg/dwarf"
	"github.com/go-delve/delve/pkg/dwarf/leb128"
)

const (
	_DW_FORM_block      = 0x09
	_DW_FORM_block1     = 0x0a
	_DW_FORM_block2     = 0x03
	_DW_FORM_block4     = 0x04
	_DW_FORM_data1      = 0x0b
	_DW_FORM_data2      = 0x05
	_DW_FORM_data4      = 0x06
	_DW_FORM_data8      = 0x07
	_DW_FORM_data16     = 0x1e
	_DW_FORM_flag       = 0x0c
	_DW_FORM_line_strp  = 0x1f
	_DW_FORM_sdata      = 0x0d
	_DW_FORM_sec_offset = 0x17
	_DW_FORM_string     = 0x08
	_DW_FORM_strp       = 0x0e
	_DW_FORM_strx       = 0x1a
	_DW_FORM_strx1      = 0x25
	_DW_FORM_strx2      = 0x26
	_DW_FORM_strx3      = 0x27
	_DW_FORM_strx4      = 0x28
	_DW_FORM_udata      = 0x0f
)

const (
	_DW_LNCT_path = 0x1 + iota
	_DW_LNCT_directory_index
	_DW_LNCT_timestamp
	_DW_LNCT_size
	_DW_LNCT_MD5
)

var ErrBufferUnderflow = errors.New("buffer underflow")

type formReader struct {
	logf         func(string, ...interface{})
	contentTypes []uint64
	formCodes    []uint64

	contentType uint64
	formCode    uint64

	block []byte
	u64   uint64
	i64   int64
	str   string
	err   error

	nexti int
}

func readEntryFormat(buf *bytes.Buffer, logf func(string, ...interface{})) *formReader {
	if buf.Len() < 1 {
		return nil
	}
	count := buf.Next(1)[0]
	r := &formReader{
		logf:         logf,
		contentTypes: make([]uint64, count),
		formCodes:    make([]uint64, count),
	}
	for i := range r.contentTypes {
		r.contentTypes[i], _ = leb128.DecodeUnsigned(buf)
		r.formCodes[i], _ = leb128.DecodeUnsigned(buf)
	}
	return r
}

func (rdr *formReader) reset() {
	rdr.err = nil
	rdr.nexti = 0
}

func (rdr *formReader) next(buf *bytes.Buffer) bool {
	if rdr.err != nil {
		return false
	}
	if rdr.nexti >= len(rdr.contentTypes) {
		return false
	}

	rdr.contentType = rdr.contentTypes[rdr.nexti]
	rdr.formCode = rdr.formCodes[rdr.nexti]

	switch rdr.formCode {
	case _DW_FORM_block:
		n, _ := leb128.DecodeUnsigned(buf)
		rdr.readBlock(buf, n)

	case _DW_FORM_block1:
		if buf.Len() < 1 {
			rdr.err = ErrBufferUnderflow
			return false
		}
		rdr.readBlock(buf, uint64(buf.Next(1)[0]))

	case _DW_FORM_block2:
		if buf.Len() < 2 {
			rdr.err = ErrBufferUnderflow
			return false
		}
		rdr.readBlock(buf, uint64(binary.LittleEndian.Uint16(buf.Next(2))))

	case _DW_FORM_block4:
		if buf.Len() < 4 {
			rdr.err = ErrBufferUnderflow
			return false
		}
		rdr.readBlock(buf, uint64(binary.LittleEndian.Uint32(buf.Next(4))))

	case _DW_FORM_data1, _DW_FORM_flag, _DW_FORM_strx1:
		if buf.Len() < 1 {
			rdr.err = ErrBufferUnderflow
			return false
		}
		rdr.u64 = uint64(buf.Next(1)[0])

	case _DW_FORM_data2, _DW_FORM_strx2:
		if buf.Len() < 2 {
			rdr.err = ErrBufferUnderflow
			return false
		}
		rdr.u64 = uint64(binary.LittleEndian.Uint16(buf.Next(2)))

	case _DW_FORM_data4, _DW_FORM_line_strp, _DW_FORM_sec_offset, _DW_FORM_strp, _DW_FORM_strx4:
		if buf.Len() < 4 {
			rdr.err = ErrBufferUnderflow
			return false
		}
		rdr.u64 = uint64(binary.LittleEndian.Uint32(buf.Next(4)))

	case _DW_FORM_data8:
		if buf.Len() < 8 {
			rdr.err = ErrBufferUnderflow
			return false
		}
		rdr.u64 = binary.LittleEndian.Uint64(buf.Next(8))

	case _DW_FORM_data16:
		rdr.readBlock(buf, 16)

	case _DW_FORM_sdata:
		rdr.i64, _ = leb128.DecodeSigned(buf)

	case _DW_FORM_udata, _DW_FORM_strx:
		rdr.u64, _ = leb128.DecodeUnsigned(buf)

	case _DW_FORM_string:
		rdr.str, _ = dwarf.ReadString(buf)

	case _DW_FORM_strx3:
		if buf.Len() < 3 {
			rdr.err = ErrBufferUnderflow
			return false
		}
		rdr.u64 = uint64(binary.LittleEndian.Uint32(append(buf.Next(3), 0x0)))

	case ^uint64(0):
		// do nothing

	default:
		if rdr.logf != nil {
			rdr.logf("unknown form code %#x", rdr.formCode)
		}
		rdr.formCodes[rdr.nexti] = ^uint64(0) // only print error once
	}

	rdr.nexti++
	return true
}

func (rdr *formReader) readBlock(buf *bytes.Buffer, n uint64) {
	if uint64(buf.Len()) < n {
		rdr.err = ErrBufferUnderflow
		return
	}
	if cap(rdr.block) < int(n) {
		rdr.block = make([]byte, 0, n)
	}
	rdr.block = rdr.block[:n]
	buf.Read(rdr.block)
}