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)
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)
}

@ -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