proc: fix findCompileUnitForOffset when plugins are used

Splits the compileUnits slice between images so that we can search for
an offset inside the debug info of a specific image file.
This commit is contained in:
aarzilli
2020-04-15 10:42:22 +02:00
committed by Derek Parker
parent 96890bbe1e
commit 8f5df19948
2 changed files with 32 additions and 25 deletions

View File

@ -84,8 +84,6 @@ type BinaryInfo struct {
frameEntries frame.FrameDescriptionEntries frameEntries frame.FrameDescriptionEntries
compileUnits []*compileUnit // compileUnits is sorted by increasing DWARF offset
types map[string]dwarfRef types map[string]dwarfRef
packageVars []packageVar // packageVars is a list of all global/package variables in debug_info, sorted by address packageVars []packageVar // packageVars is a list of all global/package variables in debug_info, sorted by address
@ -520,14 +518,17 @@ func (err *ErrCouldNotFindLine) Error() string {
func (bi *BinaryInfo) LineToPC(filename string, lineno int) (pcs []uint64, err error) { func (bi *BinaryInfo) LineToPC(filename string, lineno int) (pcs []uint64, err error) {
fileFound := false fileFound := false
var pc uint64 var pc uint64
for _, cu := range bi.compileUnits { pcsearch:
if cu.lineInfo == nil || cu.lineInfo.Lookup[filename] == nil { for _, image := range bi.Images {
continue for _, cu := range image.compileUnits {
} if cu.lineInfo == nil || cu.lineInfo.Lookup[filename] == nil {
fileFound = true continue
pc = cu.lineInfo.LineToPC(filename, lineno) }
if pc != 0 { fileFound = true
break pc = cu.lineInfo.LineToPC(filename, lineno)
if pc != 0 {
break pcsearch
}
} }
} }
@ -580,9 +581,11 @@ func (bi *BinaryInfo) AllPCsForFileLines(filename string, linenos []int) map[int
for _, line := range linenos { for _, line := range linenos {
r[line] = make([]uint64, 0, 1) r[line] = make([]uint64, 0, 1)
} }
for _, cu := range bi.compileUnits { for _, image := range bi.Images {
if cu.lineInfo != nil && cu.lineInfo.Lookup[filename] != nil { for _, cu := range image.compileUnits {
cu.lineInfo.AllPCsForFileLines(filename, r) if cu.lineInfo != nil && cu.lineInfo.Lookup[filename] != nil {
cu.lineInfo.AllPCsForFileLines(filename, r)
}
} }
} }
return r return r
@ -648,6 +651,8 @@ type Image struct {
typeCache map[dwarf.Offset]godwarf.Type typeCache map[dwarf.Offset]godwarf.Type
compileUnits []*compileUnit // compileUnits is sorted by increasing DWARF offset
dwarfTreeCache *simplelru.LRU dwarfTreeCache *simplelru.LRU
// runtimeTypeToDIE maps between the offset of a runtime._type in // runtimeTypeToDIE maps between the offset of a runtime._type in
@ -871,7 +876,7 @@ func (bi *BinaryInfo) LocationCovers(entry *dwarf.Entry, attr dwarf.Attr) ([][2]
if !ok { if !ok {
return nil, fmt.Errorf("attribute %s of unsupported type %T", attr, a) return nil, fmt.Errorf("attribute %s of unsupported type %T", attr, a)
} }
cu := bi.findCompileUnitForOffset(entry.Offset) cu := bi.Images[0].findCompileUnitForOffset(entry.Offset)
if cu == nil { if cu == nil {
return nil, errors.New("could not find compile unit") return nil, errors.New("could not find compile unit")
} }
@ -938,17 +943,19 @@ func (bi *BinaryInfo) loclistEntry(off int64, pc uint64) []byte {
// findCompileUnit returns the compile unit containing address pc. // findCompileUnit returns the compile unit containing address pc.
func (bi *BinaryInfo) findCompileUnit(pc uint64) *compileUnit { func (bi *BinaryInfo) findCompileUnit(pc uint64) *compileUnit {
for _, cu := range bi.compileUnits { for _, image := range bi.Images {
for _, rng := range cu.ranges { for _, cu := range image.compileUnits {
if pc >= rng[0] && pc < rng[1] { for _, rng := range cu.ranges {
return cu if pc >= rng[0] && pc < rng[1] {
return cu
}
} }
} }
} }
return nil return nil
} }
func (bi *BinaryInfo) findCompileUnitForOffset(off dwarf.Offset) *compileUnit { func (bi *Image) findCompileUnitForOffset(off dwarf.Offset) *compileUnit {
i := sort.Search(len(bi.compileUnits), func(i int) bool { i := sort.Search(len(bi.compileUnits), func(i int) bool {
return bi.compileUnits[i].offset >= off return bi.compileUnits[i].offset >= off
}) })
@ -960,7 +967,7 @@ func (bi *BinaryInfo) findCompileUnitForOffset(off dwarf.Offset) *compileUnit {
// Producer returns the value of DW_AT_producer. // Producer returns the value of DW_AT_producer.
func (bi *BinaryInfo) Producer() string { func (bi *BinaryInfo) Producer() string {
for _, cu := range bi.compileUnits { for _, cu := range bi.Images[0].compileUnits {
if cu.isgo && cu.producer != "" { if cu.isgo && cu.producer != "" {
return cu.producer return cu.producer
} }
@ -1569,7 +1576,7 @@ func (bi *BinaryInfo) loadDebugInfoMaps(image *Image, debugLineBytes []byte, wg
if cu.isgo && gopkg != "" { if cu.isgo && gopkg != "" {
bi.PackageMap[gopkg] = append(bi.PackageMap[gopkg], escapePackagePath(strings.Replace(cu.name, "\\", "/", -1))) bi.PackageMap[gopkg] = append(bi.PackageMap[gopkg], escapePackagePath(strings.Replace(cu.name, "\\", "/", -1)))
} }
bi.compileUnits = append(bi.compileUnits, cu) image.compileUnits = append(image.compileUnits, cu)
if entry.Children { if entry.Children {
bi.loadDebugInfoMapsCompileUnit(ctxt, image, reader, cu) bi.loadDebugInfoMapsCompileUnit(ctxt, image, reader, cu)
} }
@ -1583,7 +1590,7 @@ func (bi *BinaryInfo) loadDebugInfoMaps(image *Image, debugLineBytes []byte, wg
} }
} }
sort.Sort(compileUnitsByOffset(bi.compileUnits)) sort.Sort(compileUnitsByOffset(image.compileUnits))
sort.Sort(functionsDebugInfoByEntry(bi.Functions)) sort.Sort(functionsDebugInfoByEntry(bi.Functions))
sort.Sort(packageVarsByAddr(bi.packageVars)) sort.Sort(packageVarsByAddr(bi.packageVars))
@ -1593,7 +1600,7 @@ func (bi *BinaryInfo) loadDebugInfoMaps(image *Image, debugLineBytes []byte, wg
} }
bi.Sources = []string{} bi.Sources = []string{}
for _, cu := range bi.compileUnits { for _, cu := range image.compileUnits {
if cu.lineInfo != nil { if cu.lineInfo != nil {
for _, fileEntry := range cu.lineInfo.FileNames { for _, fileEntry := range cu.lineInfo.FileNames {
bi.Sources = append(bi.Sources, fileEntry.Path) bi.Sources = append(bi.Sources, fileEntry.Path)
@ -1997,7 +2004,7 @@ type PackageBuildInfo struct {
// files constituting the package. // files constituting the package.
func (bi *BinaryInfo) ListPackagesBuildInfo(includeFiles bool) []*PackageBuildInfo { func (bi *BinaryInfo) ListPackagesBuildInfo(includeFiles bool) []*PackageBuildInfo {
m := make(map[string]*PackageBuildInfo) m := make(map[string]*PackageBuildInfo)
for _, cu := range bi.compileUnits { for _, cu := range bi.Images[0].compileUnits {
if cu.image != bi.Images[0] || !cu.isgo || cu.lineInfo == nil { if cu.image != bi.Images[0] || !cu.isgo || cu.lineInfo == nil {
//TODO(aarzilli): what's the correct thing to do for plugins? //TODO(aarzilli): what's the correct thing to do for plugins?
continue continue

View File

@ -588,7 +588,7 @@ func newVariable(name string, addr uintptr, dwarfType godwarf.Type, bi *BinaryIn
// b. anonymous struct types (they contain the '{' character) // b. anonymous struct types (they contain the '{' character)
// c. Go internal struct types used to describe maps (they contain the '<' // c. Go internal struct types used to describe maps (they contain the '<'
// character). // character).
cu := bi.findCompileUnitForOffset(dwarfType.Common().Offset) cu := bi.Images[dwarfType.Common().Index].findCompileUnitForOffset(dwarfType.Common().Offset)
if cu != nil && cu.isgo { if cu != nil && cu.isgo {
dwarfType = &godwarf.TypedefType{ dwarfType = &godwarf.TypedefType{
CommonType: *(dwarfType.Common()), CommonType: *(dwarfType.Common()),