mirror of
https://github.com/go-delve/delve.git
synced 2025-10-29 17:56:45 +08:00
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:
committed by
Alessandro Arzilli
parent
5da5eee10d
commit
c902522a8c
81
pkg/dwarf/loclist/loclist.go
Normal file
81
pkg/dwarf/loclist/loclist.go
Normal 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)
|
||||||
|
}
|
||||||
@ -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)
|
||||||
|
|||||||
@ -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{
|
||||||
|
|||||||
Reference in New Issue
Block a user