mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 10:47:27 +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:
		 Derek Parker
					Derek Parker
				
			
				
					committed by
					
						 Alessandro Arzilli
						Alessandro Arzilli
					
				
			
			
				
	
			
			
			 Alessandro Arzilli
						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