diff --git a/pkg/proc/bininfo.go b/pkg/proc/bininfo.go index 8bda0702..fde4cb45 100644 --- a/pkg/proc/bininfo.go +++ b/pkg/proc/bininfo.go @@ -1917,10 +1917,8 @@ func (bi *BinaryInfo) addAbstractSubprogram(entry *dwarf.Entry, ctxt *loadDebugI name, ok := subprogramEntryName(entry, cu) if !ok { bi.logger.Warnf("reading debug_info: abstract subprogram without name at %#x", entry.Offset) - if entry.Children { - reader.SkipChildren() - } - return + // In some cases clang produces abstract subprograms that do not have a + // name, but we should process them anyway. } if entry.Children { @@ -1950,6 +1948,7 @@ func (bi *BinaryInfo) addConcreteInlinedSubprogram(entry *dwarf.Entry, originOff fn.offset = entry.Offset fn.Entry = lowpc fn.End = highpc + fn.cu = cu if entry.Children { bi.loadDebugInfoMapsInlinedCalls(ctxt, reader, cu) @@ -1962,29 +1961,25 @@ func (bi *BinaryInfo) addConcreteSubprogram(entry *dwarf.Entry, ctxt *loadDebugI lowpc, highpc, ok := subprogramEntryRange(entry, cu.image) if !ok { bi.logger.Warnf("reading debug_info: concrete subprogram without address range at %#x", entry.Offset) - if entry.Children { - reader.SkipChildren() - } - return + // When clang inlines a function, in some cases, it produces a concrete + // subprogram without address range and then inlined calls that reference + // it, instead of producing an abstract subprogram. + // It is unclear if this behavior is standard. } name, ok := subprogramEntryName(entry, cu) if !ok { bi.logger.Warnf("reading debug_info: concrete subprogram without name at %#x", entry.Offset) - if entry.Children { - reader.SkipChildren() - } - return } - fn := Function{ - Name: name, - Entry: lowpc, - End: highpc, - offset: entry.Offset, - cu: cu, - } - bi.Functions = append(bi.Functions, fn) + originIdx := ctxt.lookupAbstractOrigin(bi, entry.Offset) + fn := &bi.Functions[originIdx] + + fn.Name = name + fn.Entry = lowpc + fn.End = highpc + fn.offset = entry.Offset + fn.cu = cu if entry.Children { bi.loadDebugInfoMapsInlinedCalls(ctxt, reader, cu) @@ -2030,9 +2025,6 @@ func (bi *BinaryInfo) loadDebugInfoMapsInlinedCalls(ctxt *loadDebugInfoMapsConte continue } - originIdx := ctxt.lookupAbstractOrigin(bi, originOffset) - fn := &bi.Functions[originIdx] - lowpc, highpc, ok := subprogramEntryRange(entry, cu.image) if !ok { bi.logger.Warnf("reading debug_info: inlined call without address range at %#x", entry.Offset) @@ -2054,12 +2046,19 @@ func (bi *BinaryInfo) loadDebugInfoMapsInlinedCalls(ctxt *loadDebugInfoMapsConte continue } + originIdx := ctxt.lookupAbstractOrigin(bi, originOffset) + fn := &bi.Functions[originIdx] + fn.InlinedCalls = append(fn.InlinedCalls, InlinedCall{ cu: cu, LowPC: lowpc, HighPC: highpc, }) + if fn.cu == nil { + fn.cu = cu + } + fl := fileLine{callfile, int(callline)} bi.inlinedCallLines[fl] = append(bi.inlinedCallLines[fl], lowpc) } diff --git a/pkg/proc/types.go b/pkg/proc/types.go index 31bb8489..2a5dc303 100644 --- a/pkg/proc/types.go +++ b/pkg/proc/types.go @@ -103,6 +103,7 @@ func (ctxt *loadDebugInfoMapsContext) lookupAbstractOrigin(bi *BinaryInfo, off d if !ok { bi.Functions = append(bi.Functions, Function{}) r = len(bi.Functions) - 1 + bi.Functions[r].offset = off ctxt.abstractOriginTable[off] = r } return r