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)
}
|