pkg/proc,pkg/dwarf: Introduce loclist package

Move the loclist code out of proc and into its own package in
`pkg/dwarf`.
This commit is contained in:
Derek Parker
2019-11-12 11:44:08 -08:00
committed by Alessandro Arzilli
parent 5da5eee10d
commit c902522a8c
3 changed files with 101 additions and 83 deletions

View File

@ -0,0 +1,81 @@
package loclist
import (
"encoding/binary"
)
// Reader parses and presents DWARF loclist information.
type Reader struct {
data []byte
cur int
ptrSz int
}
// New returns an initialized loclist Reader.
func New(data []byte, ptrSz int) *Reader {
return &Reader{data: data, ptrSz: ptrSz}
}
// Empty returns true if this reader has no data.
func (rdr *Reader) Empty() bool {
return rdr.data == nil
}
// Seek moves the data pointer to the specified offset.
func (rdr *Reader) Seek(off int) {
rdr.cur = off
}
// Next advances the reader to the next loclist entry, returning
// the entry and true if successful, or nil, false if not.
func (rdr *Reader) Next(e *Entry) bool {
e.LowPC = rdr.oneAddr()
e.HighPC = rdr.oneAddr()
if e.LowPC == 0 && e.HighPC == 0 {
return false
}
if e.BaseAddressSelection() {
e.Instr = nil
return true
}
instrlen := binary.LittleEndian.Uint16(rdr.read(2))
e.Instr = rdr.read(int(instrlen))
return true
}
func (rdr *Reader) read(sz int) []byte {
r := rdr.data[rdr.cur : rdr.cur+sz]
rdr.cur += sz
return r
}
func (rdr *Reader) oneAddr() uint64 {
switch rdr.ptrSz {
case 4:
addr := binary.LittleEndian.Uint32(rdr.read(rdr.ptrSz))
if addr == ^uint32(0) {
return ^uint64(0)
}
return uint64(addr)
case 8:
addr := uint64(binary.LittleEndian.Uint64(rdr.read(rdr.ptrSz)))
return addr
default:
panic("bad address size")
}
}
// Entry represents a single entry in the loclist section.
type Entry struct {
LowPC, HighPC uint64
Instr []byte
}
// BaseAddressSelection returns true if entry.highpc should
// be used as the base address for subsequent entries.
func (e *Entry) BaseAddressSelection() bool {
return e.LowPC == ^uint64(0)
}

View File

@ -24,6 +24,7 @@ import (
"github.com/go-delve/delve/pkg/dwarf/frame" "github.com/go-delve/delve/pkg/dwarf/frame"
"github.com/go-delve/delve/pkg/dwarf/godwarf" "github.com/go-delve/delve/pkg/dwarf/godwarf"
"github.com/go-delve/delve/pkg/dwarf/line" "github.com/go-delve/delve/pkg/dwarf/line"
"github.com/go-delve/delve/pkg/dwarf/loclist"
"github.com/go-delve/delve/pkg/dwarf/op" "github.com/go-delve/delve/pkg/dwarf/op"
"github.com/go-delve/delve/pkg/dwarf/reader" "github.com/go-delve/delve/pkg/dwarf/reader"
"github.com/go-delve/delve/pkg/goversion" "github.com/go-delve/delve/pkg/goversion"
@ -233,70 +234,6 @@ type packageVar struct {
addr uint64 addr uint64
} }
type loclistReader struct {
data []byte
cur int
ptrSz int
}
func (rdr *loclistReader) Seek(off int) {
rdr.cur = off
}
func (rdr *loclistReader) read(sz int) []byte {
r := rdr.data[rdr.cur : rdr.cur+sz]
rdr.cur += sz
return r
}
func (rdr *loclistReader) oneAddr() uint64 {
switch rdr.ptrSz {
case 4:
addr := binary.LittleEndian.Uint32(rdr.read(rdr.ptrSz))
if addr == ^uint32(0) {
return ^uint64(0)
}
return uint64(addr)
case 8:
addr := uint64(binary.LittleEndian.Uint64(rdr.read(rdr.ptrSz)))
return addr
default:
panic("bad address size")
}
}
func (rdr *loclistReader) Next(e *loclistEntry) bool {
e.lowpc = rdr.oneAddr()
e.highpc = rdr.oneAddr()
if e.lowpc == 0 && e.highpc == 0 {
return false
}
if e.BaseAddressSelection() {
e.instr = nil
return true
}
instrlen := binary.LittleEndian.Uint16(rdr.read(2))
e.instr = rdr.read(int(instrlen))
return true
}
type loclistEntry struct {
lowpc, highpc uint64
instr []byte
}
type runtimeTypeDIE struct {
offset dwarf.Offset
kind int64
}
func (e *loclistEntry) BaseAddressSelection() bool {
return e.lowpc == ^uint64(0)
}
type buildIDHeader struct { type buildIDHeader struct {
Namesz uint32 Namesz uint32
Descsz uint32 Descsz uint32
@ -529,7 +466,7 @@ type Image struct {
dwarf *dwarf.Data dwarf *dwarf.Data
dwarfReader *dwarf.Reader dwarfReader *dwarf.Reader
loclist loclistReader loclist *loclist.Reader
typeCache map[dwarf.Offset]godwarf.Type typeCache map[dwarf.Offset]godwarf.Type
@ -670,18 +607,13 @@ func (bi *BinaryInfo) LoadImageFromData(dwdata *dwarf.Data, debugFrameBytes, deb
bi.frameEntries = frame.Parse(debugFrameBytes, frame.DwarfEndian(debugFrameBytes), 0) bi.frameEntries = frame.Parse(debugFrameBytes, frame.DwarfEndian(debugFrameBytes), 0)
} }
image.loclistInit(debugLocBytes, bi.Arch.PtrSize()) image.loclist = loclist.New(debugLocBytes, bi.Arch.PtrSize())
bi.loadDebugInfoMaps(image, debugLineBytes, nil, nil) bi.loadDebugInfoMaps(image, debugLineBytes, nil, nil)
bi.Images = append(bi.Images, image) bi.Images = append(bi.Images, image)
} }
func (image *Image) loclistInit(data []byte, ptrSz int) {
image.loclist.data = data
image.loclist.ptrSz = ptrSz
}
func (bi *BinaryInfo) locationExpr(entry reader.Entry, attr dwarf.Attr, pc uint64) ([]byte, string, error) { func (bi *BinaryInfo) locationExpr(entry reader.Entry, attr dwarf.Attr, pc uint64) ([]byte, string, error) {
a := entry.Val(attr) a := entry.Val(attr)
if a == nil { if a == nil {
@ -729,19 +661,19 @@ func (bi *BinaryInfo) LocationCovers(entry *dwarf.Entry, attr dwarf.Attr) ([][2]
image := cu.image image := cu.image
base := cu.lowPC base := cu.lowPC
if image == nil || image.loclist.data == nil { if image == nil || image.loclist.Empty() {
return nil, errors.New("malformed executable") return nil, errors.New("malformed executable")
} }
r := [][2]uint64{} r := [][2]uint64{}
var e loclist.Entry
image.loclist.Seek(int(off)) image.loclist.Seek(int(off))
var e loclistEntry
for image.loclist.Next(&e) { for image.loclist.Next(&e) {
if e.BaseAddressSelection() { if e.BaseAddressSelection() {
base = e.highpc base = e.HighPC
continue continue
} }
r = append(r, [2]uint64{e.lowpc + base, e.highpc + base}) r = append(r, [2]uint64{e.LowPC + base, e.HighPC + base})
} }
return r, nil return r, nil
} }
@ -768,19 +700,19 @@ func (bi *BinaryInfo) loclistEntry(off int64, pc uint64) []byte {
base = cu.lowPC base = cu.lowPC
image = cu.image image = cu.image
} }
if image == nil || image.loclist.data == nil { if image == nil || image.loclist.Empty() {
return nil return nil
} }
image.loclist.Seek(int(off)) image.loclist.Seek(int(off))
var e loclistEntry var e loclist.Entry
for image.loclist.Next(&e) { for image.loclist.Next(&e) {
if e.BaseAddressSelection() { if e.BaseAddressSelection() {
base = e.highpc base = e.HighPC
continue continue
} }
if pc >= e.lowpc+base && pc < e.highpc+base { if pc >= e.LowPC+base && pc < e.HighPC+base {
return e.instr return e.Instr
} }
} }
@ -980,7 +912,7 @@ func loadBinaryInfoElf(bi *BinaryInfo, image *Image, path string, addr uint64, w
return err return err
} }
debugLocBytes, _ := godwarf.GetDebugSectionElf(dwarfFile, "loc") debugLocBytes, _ := godwarf.GetDebugSectionElf(dwarfFile, "loc")
image.loclistInit(debugLocBytes, bi.Arch.PtrSize()) image.loclist = loclist.New(debugLocBytes, bi.Arch.PtrSize())
wg.Add(2) wg.Add(2)
go bi.parseDebugFrameElf(image, dwarfFile, wg) go bi.parseDebugFrameElf(image, dwarfFile, wg)
@ -1095,7 +1027,7 @@ func loadBinaryInfoPE(bi *BinaryInfo, image *Image, path string, entryPoint uint
return err return err
} }
debugLocBytes, _ := godwarf.GetDebugSectionPE(peFile, "loc") debugLocBytes, _ := godwarf.GetDebugSectionPE(peFile, "loc")
image.loclistInit(debugLocBytes, bi.Arch.PtrSize()) image.loclist = loclist.New(debugLocBytes, bi.Arch.PtrSize())
wg.Add(2) wg.Add(2)
go bi.parseDebugFramePE(image, peFile, wg) go bi.parseDebugFramePE(image, peFile, wg)
@ -1180,7 +1112,7 @@ func loadBinaryInfoMacho(bi *BinaryInfo, image *Image, path string, entryPoint u
return err return err
} }
debugLocBytes, _ := godwarf.GetDebugSectionMacho(exe, "loc") debugLocBytes, _ := godwarf.GetDebugSectionMacho(exe, "loc")
image.loclistInit(debugLocBytes, bi.Arch.PtrSize()) image.loclist = loclist.New(debugLocBytes, bi.Arch.PtrSize())
wg.Add(2) wg.Add(2)
go bi.parseDebugFrameMacho(image, exe, wg) go bi.parseDebugFrameMacho(image, exe, wg)

View File

@ -42,6 +42,11 @@ const (
interfacetypeFieldMhdr = "mhdr" interfacetypeFieldMhdr = "mhdr"
) )
type runtimeTypeDIE struct {
offset dwarf.Offset
kind int64
}
func pointerTo(typ godwarf.Type, arch Arch) godwarf.Type { func pointerTo(typ godwarf.Type, arch Arch) godwarf.Type {
return &godwarf.PtrType{ return &godwarf.PtrType{
CommonType: godwarf.CommonType{ CommonType: godwarf.CommonType{