-
Notifications
You must be signed in to change notification settings - Fork 0
/
parse_util.go
192 lines (162 loc) · 3.93 KB
/
parse_util.go
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
package line
import (
"bytes"
"encoding/binary"
"errors"
"github.com/undoio/delve/pkg/dwarf/util"
)
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], _ = util.DecodeULEB128(buf)
r.formCodes[i], _ = util.DecodeULEB128(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, _ := util.DecodeULEB128(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, _ = util.DecodeSLEB128(buf)
case _DW_FORM_udata, _DW_FORM_strx:
rdr.u64, _ = util.DecodeULEB128(buf)
case _DW_FORM_string:
rdr.str, _ = util.ParseString(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)
}