2014-06-02 21:33:02 +00:00
|
|
|
// Package frame contains data structures and
|
|
|
|
// related functions for parsing and searching
|
|
|
|
// through Dwarf .debug_frame data.
|
|
|
|
package frame
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/binary"
|
2014-06-29 16:52:21 +00:00
|
|
|
|
2014-10-15 14:21:46 +00:00
|
|
|
"github.com/derekparker/delve/dwarf/util"
|
2014-06-02 21:33:02 +00:00
|
|
|
)
|
|
|
|
|
2014-06-25 19:14:29 +00:00
|
|
|
type parsefunc func(*parseContext) parsefunc
|
2014-06-06 21:05:26 +00:00
|
|
|
|
|
|
|
type parseContext struct {
|
|
|
|
Buf *bytes.Buffer
|
2014-08-07 16:03:42 +00:00
|
|
|
Entries *FrameDescriptionEntries
|
2014-06-07 00:04:15 +00:00
|
|
|
Common *CommonInformationEntry
|
2014-06-25 19:14:29 +00:00
|
|
|
Frame *FrameDescriptionEntry
|
2014-06-06 21:05:26 +00:00
|
|
|
Length uint32
|
|
|
|
}
|
2014-06-02 21:33:02 +00:00
|
|
|
|
2014-06-06 20:28:47 +00:00
|
|
|
// Parse takes in data (a byte slice) and returns a slice of
|
2014-06-02 21:33:02 +00:00
|
|
|
// CommonInformationEntry structures. Each CommonInformationEntry
|
2014-06-25 19:14:29 +00:00
|
|
|
// has a slice of FrameDescriptionEntry structures.
|
2014-08-07 16:03:42 +00:00
|
|
|
func Parse(data []byte) *FrameDescriptionEntries {
|
2014-06-02 21:33:02 +00:00
|
|
|
var (
|
2014-06-25 19:14:29 +00:00
|
|
|
buf = bytes.NewBuffer(data)
|
2014-08-07 16:03:42 +00:00
|
|
|
pctx = &parseContext{Buf: buf, Entries: NewFrameIndex()}
|
2014-06-02 21:33:02 +00:00
|
|
|
)
|
|
|
|
|
2014-06-06 21:05:26 +00:00
|
|
|
for fn := parseLength; buf.Len() != 0; {
|
2014-06-25 19:14:29 +00:00
|
|
|
fn = fn(pctx)
|
2014-06-02 21:33:02 +00:00
|
|
|
}
|
|
|
|
|
2014-06-06 21:05:26 +00:00
|
|
|
return pctx.Entries
|
2014-06-02 21:33:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func cieEntry(data []byte) bool {
|
|
|
|
return bytes.Equal(data, []byte{0xff, 0xff, 0xff, 0xff})
|
|
|
|
}
|
|
|
|
|
2014-06-25 19:14:29 +00:00
|
|
|
func parseLength(ctx *parseContext) parsefunc {
|
2014-08-05 16:00:41 +00:00
|
|
|
var data = ctx.Buf.Next(8)
|
2014-06-25 19:14:29 +00:00
|
|
|
|
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-06-02 21:33:02 +00:00
|
|
|
|
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-06-02 21:33:02 +00:00
|
|
|
}
|
|
|
|
|
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-06-02 21:33:02 +00:00
|
|
|
}
|
|
|
|
|
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])
|
2014-06-02 21:33:02 +00:00
|
|
|
|
2014-08-04 23:02:08 +00:00
|
|
|
// Insert into the tree after setting address range begin
|
|
|
|
// otherwise compares won't work.
|
|
|
|
ctx.Entries.Put(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:]
|
2014-06-06 21:05:26 +00:00
|
|
|
ctx.Length = 0
|
2014-06-02 21:33:02 +00:00
|
|
|
|
2014-06-25 19:14:29 +00:00
|
|
|
return parseLength
|
2014-06-02 21:33:02 +00:00
|
|
|
}
|
|
|
|
|
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-06-02 21:33:02 +00:00
|
|
|
|
2014-08-05 16:00:41 +00:00
|
|
|
// parse augmentation
|
|
|
|
ctx.Common.Augmentation, _ = util.ParseString(buf)
|
2014-06-02 21:33:02 +00:00
|
|
|
|
2014-08-05 16:00:41 +00:00
|
|
|
// parse code alignment factor
|
|
|
|
ctx.Common.CodeAlignmentFactor, _ = util.DecodeULEB128(buf)
|
2014-06-02 21:33:02 +00:00
|
|
|
|
2014-08-05 16:00:41 +00:00
|
|
|
// parse data alignment factor
|
|
|
|
ctx.Common.DataAlignmentFactor, _ = util.DecodeSLEB128(buf)
|
2014-06-06 21:05:26 +00:00
|
|
|
|
2014-08-05 16:00:41 +00:00
|
|
|
// parse return address register
|
|
|
|
ctx.Common.ReturnAddressRegister, _ = util.DecodeULEB128(buf)
|
2014-06-02 21:33:02 +00:00
|
|
|
|
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))
|
2014-06-06 21:05:26 +00:00
|
|
|
ctx.Length = 0
|
2014-06-02 21:33:02 +00:00
|
|
|
|
2014-06-25 19:14:29 +00:00
|
|
|
return parseLength
|
2014-06-02 21:33:02 +00:00
|
|
|
}
|