proc: be more lenient when parsing debug_info (#2394)

- allow a concrete subprogram to be treated as the abstract origin for an inlined call
- allow nameless concrete and abstract subprograms

Fixes #2393
This commit is contained in:
Alessandro Arzilli 2021-04-05 20:50:59 +02:00 committed by GitHub
parent da27e34217
commit 618f366998
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 23 deletions

@ -1917,10 +1917,8 @@ func (bi *BinaryInfo) addAbstractSubprogram(entry *dwarf.Entry, ctxt *loadDebugI
name, ok := subprogramEntryName(entry, cu) name, ok := subprogramEntryName(entry, cu)
if !ok { if !ok {
bi.logger.Warnf("reading debug_info: abstract subprogram without name at %#x", entry.Offset) bi.logger.Warnf("reading debug_info: abstract subprogram without name at %#x", entry.Offset)
if entry.Children { // In some cases clang produces abstract subprograms that do not have a
reader.SkipChildren() // name, but we should process them anyway.
}
return
} }
if entry.Children { if entry.Children {
@ -1950,6 +1948,7 @@ func (bi *BinaryInfo) addConcreteInlinedSubprogram(entry *dwarf.Entry, originOff
fn.offset = entry.Offset fn.offset = entry.Offset
fn.Entry = lowpc fn.Entry = lowpc
fn.End = highpc fn.End = highpc
fn.cu = cu
if entry.Children { if entry.Children {
bi.loadDebugInfoMapsInlinedCalls(ctxt, reader, cu) 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) lowpc, highpc, ok := subprogramEntryRange(entry, cu.image)
if !ok { if !ok {
bi.logger.Warnf("reading debug_info: concrete subprogram without address range at %#x", entry.Offset) bi.logger.Warnf("reading debug_info: concrete subprogram without address range at %#x", entry.Offset)
if entry.Children { // When clang inlines a function, in some cases, it produces a concrete
reader.SkipChildren() // subprogram without address range and then inlined calls that reference
} // it, instead of producing an abstract subprogram.
return // It is unclear if this behavior is standard.
} }
name, ok := subprogramEntryName(entry, cu) name, ok := subprogramEntryName(entry, cu)
if !ok { if !ok {
bi.logger.Warnf("reading debug_info: concrete subprogram without name at %#x", entry.Offset) bi.logger.Warnf("reading debug_info: concrete subprogram without name at %#x", entry.Offset)
if entry.Children {
reader.SkipChildren()
}
return
} }
fn := Function{ originIdx := ctxt.lookupAbstractOrigin(bi, entry.Offset)
Name: name, fn := &bi.Functions[originIdx]
Entry: lowpc,
End: highpc, fn.Name = name
offset: entry.Offset, fn.Entry = lowpc
cu: cu, fn.End = highpc
} fn.offset = entry.Offset
bi.Functions = append(bi.Functions, fn) fn.cu = cu
if entry.Children { if entry.Children {
bi.loadDebugInfoMapsInlinedCalls(ctxt, reader, cu) bi.loadDebugInfoMapsInlinedCalls(ctxt, reader, cu)
@ -2030,9 +2025,6 @@ func (bi *BinaryInfo) loadDebugInfoMapsInlinedCalls(ctxt *loadDebugInfoMapsConte
continue continue
} }
originIdx := ctxt.lookupAbstractOrigin(bi, originOffset)
fn := &bi.Functions[originIdx]
lowpc, highpc, ok := subprogramEntryRange(entry, cu.image) lowpc, highpc, ok := subprogramEntryRange(entry, cu.image)
if !ok { if !ok {
bi.logger.Warnf("reading debug_info: inlined call without address range at %#x", entry.Offset) 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 continue
} }
originIdx := ctxt.lookupAbstractOrigin(bi, originOffset)
fn := &bi.Functions[originIdx]
fn.InlinedCalls = append(fn.InlinedCalls, InlinedCall{ fn.InlinedCalls = append(fn.InlinedCalls, InlinedCall{
cu: cu, cu: cu,
LowPC: lowpc, LowPC: lowpc,
HighPC: highpc, HighPC: highpc,
}) })
if fn.cu == nil {
fn.cu = cu
}
fl := fileLine{callfile, int(callline)} fl := fileLine{callfile, int(callline)}
bi.inlinedCallLines[fl] = append(bi.inlinedCallLines[fl], lowpc) bi.inlinedCallLines[fl] = append(bi.inlinedCallLines[fl], lowpc)
} }

@ -103,6 +103,7 @@ func (ctxt *loadDebugInfoMapsContext) lookupAbstractOrigin(bi *BinaryInfo, off d
if !ok { if !ok {
bi.Functions = append(bi.Functions, Function{}) bi.Functions = append(bi.Functions, Function{})
r = len(bi.Functions) - 1 r = len(bi.Functions) - 1
bi.Functions[r].offset = off
ctxt.abstractOriginTable[off] = r ctxt.abstractOriginTable[off] = r
} }
return r return r