delve/dwarf/frame/parser.go

103 lines
2.6 KiB
Go
Raw Normal View History

// Package frame contains data structures and
// related functions for parsing and searching
// through Dwarf .debug_frame data.
package frame
import (
"bytes"
"encoding/binary"
2014-10-15 14:21:46 +00:00
"github.com/derekparker/delve/dwarf/util"
)
type parsefunc func(*parseContext) parsefunc
type parseContext struct {
Buf *bytes.Buffer
Entries FrameDescriptionEntries
2014-06-07 00:04:15 +00:00
Common *CommonInformationEntry
Frame *FrameDescriptionEntry
Length uint32
}
2014-06-06 20:28:47 +00:00
// 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) FrameDescriptionEntries {
var (
buf = bytes.NewBuffer(data)
2014-08-07 16:03:42 +00:00
pctx = &parseContext{Buf: buf, Entries: NewFrameIndex()}
)
for fn := parseLength; buf.Len() != 0; {
fn = fn(pctx)
}
return pctx.Entries
}
func cieEntry(data []byte) bool {
return bytes.Equal(data, []byte{0xff, 0xff, 0xff, 0xff})
}
func parseLength(ctx *parseContext) parsefunc {
2014-08-05 16:00:41 +00:00
var data = ctx.Buf.Next(8)
2014-08-05 16:00:41 +00:00
ctx.Length = binary.LittleEndian.Uint32(data[:4]) - 4 // take off the length of the CIE id / CIE pointer.
2014-08-05 16:00:41 +00:00
if cieEntry(data[4:]) {
2014-06-07 00:04:15 +00:00
ctx.Common = &CommonInformationEntry{Length: ctx.Length}
2014-08-05 16:00:41 +00:00
return parseCIE
}
2014-10-11 06:05:27 +00:00
ctx.Frame = &FrameDescriptionEntry{Length: ctx.Length, CIE: ctx.Common}
2014-08-05 16:00:41 +00:00
return parseFDE
}
2014-08-05 16:00:41 +00:00
func parseFDE(ctx *parseContext) parsefunc {
r := ctx.Buf.Next(int(ctx.Length))
2014-10-11 06:05:27 +00:00
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)
2014-06-07 00:04:15 +00:00
// The rest of this entry consists of the instructions
// so we can just grab all of the data from the buffer
// cursor to length.
2014-08-05 16:00:41 +00:00
ctx.Frame.Instructions = r[16:]
ctx.Length = 0
return parseLength
}
2014-08-05 16:00:41 +00:00
func parseCIE(ctx *parseContext) parsefunc {
data := ctx.Buf.Next(int(ctx.Length))
buf := bytes.NewBuffer(data)
// parse version
ctx.Common.Version = data[0]
2014-08-05 16:00:41 +00:00
// parse augmentation
ctx.Common.Augmentation, _ = util.ParseString(buf)
2014-08-05 16:00:41 +00:00
// parse code alignment factor
ctx.Common.CodeAlignmentFactor, _ = util.DecodeULEB128(buf)
2014-08-05 16:00:41 +00:00
// parse data alignment factor
ctx.Common.DataAlignmentFactor, _ = util.DecodeSLEB128(buf)
2014-08-05 16:00:41 +00:00
// parse return address register
ctx.Common.ReturnAddressRegister, _ = util.DecodeULEB128(buf)
2014-08-05 16:00:41 +00:00
// parse initial instructions
2014-06-07 00:04:15 +00:00
// The rest of this entry consists of the instructions
// so we can just grab all of the data from the buffer
// cursor to length.
2014-08-05 16:00:41 +00:00
ctx.Common.InitialInstructions = buf.Bytes() //ctx.Buf.Next(int(ctx.Length))
ctx.Length = 0
return parseLength
}