This repository has been archived by the owner on May 24, 2023. It is now read-only.
forked from go-delve/delve
-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.go
132 lines (104 loc) · 3.26 KB
/
parser.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
// Package frame contains data structures and
// related functions for parsing and searching
// through Dwarf .debug_frame data.
package frame
import (
"bytes"
"encoding/binary"
"github.com/derekparker/delve/pkg/dwarf/util"
)
type parsefunc func(*parseContext) parsefunc
type parseContext struct {
buf *bytes.Buffer
entries FrameDescriptionEntries
common *CommonInformationEntry
frame *FrameDescriptionEntry
length uint32
}
// Parse takes in data (a byte slice) and returns a slice of
// commonInformationEntry structures. Each commonInformationEntry
// has a slice of frameDescriptionEntry structures.
func Parse(data []byte, order binary.ByteOrder) FrameDescriptionEntries {
var (
buf = bytes.NewBuffer(data)
pctx = &parseContext{buf: buf, entries: NewFrameIndex()}
)
for fn := parselength; buf.Len() != 0; {
fn = fn(pctx)
}
for i := range pctx.entries {
pctx.entries[i].order = order
}
return pctx.entries
}
func cieEntry(data []byte) bool {
return bytes.Equal(data, []byte{0xff, 0xff, 0xff, 0xff})
}
func parselength(ctx *parseContext) parsefunc {
binary.Read(ctx.buf, binary.LittleEndian, &ctx.length)
if ctx.length == 0 {
// ZERO terminator
return parselength
}
var data = ctx.buf.Next(4)
ctx.length -= 4 // take off the length of the CIE id / CIE pointer.
if cieEntry(data) {
ctx.common = &CommonInformationEntry{Length: ctx.length}
return parseCIE
}
ctx.frame = &FrameDescriptionEntry{Length: ctx.length, CIE: ctx.common}
return parseFDE
}
func parseFDE(ctx *parseContext) parsefunc {
r := ctx.buf.Next(int(ctx.length))
ctx.frame.begin = binary.LittleEndian.Uint64(r[:8])
ctx.frame.end = binary.LittleEndian.Uint64(r[8:16])
// Insert into the tree after setting address range begin
// otherwise compares won't work.
ctx.entries = append(ctx.entries, ctx.frame)
// The rest of this entry consists of the instructions
// so we can just grab all of the data from the buffer
// cursor to length.
ctx.frame.Instructions = r[16:]
ctx.length = 0
return parselength
}
func parseCIE(ctx *parseContext) parsefunc {
data := ctx.buf.Next(int(ctx.length))
buf := bytes.NewBuffer(data)
// parse version
ctx.common.Version = data[0]
// parse augmentation
ctx.common.Augmentation, _ = util.ParseString(buf)
// parse code alignment factor
ctx.common.CodeAlignmentFactor, _ = util.DecodeULEB128(buf)
// parse data alignment factor
ctx.common.DataAlignmentFactor, _ = util.DecodeSLEB128(buf)
// parse return address register
ctx.common.ReturnAddressRegister, _ = util.DecodeULEB128(buf)
// parse initial instructions
// The rest of this entry consists of the instructions
// so we can just grab all of the data from the buffer
// cursor to length.
ctx.common.InitialInstructions = buf.Bytes() //ctx.buf.Next(int(ctx.length))
ctx.length = 0
return parselength
}
// DwarfEndian determines the endianness of the DWARF by using the version number field in the debug_info section
// Trick borrowed from "debug/dwarf".New()
func DwarfEndian(infoSec []byte) binary.ByteOrder {
if len(infoSec) < 6 {
return binary.BigEndian
}
x, y := infoSec[4], infoSec[5]
switch {
case x == 0 && y == 0:
return binary.BigEndian
case x == 0:
return binary.BigEndian
case y == 0:
return binary.LittleEndian
default:
return binary.BigEndian
}
}