diff --git a/go.mod b/go.mod index 2cef6737506..183f137b3c9 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/go-kit/log v0.2.0 github.com/go-ozzo/ozzo-validation/v4 v4.3.0 github.com/goburrow/cache v0.1.4 - github.com/google/pprof v0.0.0-20211214055906-6f57359322fd + github.com/google/pprof v0.0.0-20220218203455-0368bd9e19a7 github.com/google/uuid v1.3.0 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/go-grpc-middleware/providers/kit/v2 v2.0.0-20201002093600-73cf2ae9d891 @@ -25,7 +25,7 @@ require ( github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3 github.com/hashicorp/go-multierror v1.1.1 - github.com/ianlancetaylor/demangle v0.0.0-20211126204342-3ad08eb09c01 + github.com/ianlancetaylor/demangle v0.0.0-20220203202831-b7f99f1dbc96 github.com/improbable-eng/grpc-web v0.15.0 github.com/oklog/run v1.1.0 github.com/prometheus/client_golang v1.12.1 @@ -41,6 +41,7 @@ require ( go.uber.org/atomic v1.9.0 golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c + golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5 google.golang.org/grpc v1.44.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 diff --git a/go.sum b/go.sum index 4c0b81ab81d..d437b5d2e6a 100644 --- a/go.sum +++ b/go.sum @@ -961,8 +961,9 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20211122183932-1daafda22083/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= -github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= +github.com/google/pprof v0.0.0-20220218203455-0368bd9e19a7 h1:IR7vKogOtQRR3JhSl1UftKpFLnuJ2o+woqCFXqJ7wXw= +github.com/google/pprof v0.0.0-20220218203455-0368bd9e19a7/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -1117,8 +1118,8 @@ github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/ianlancetaylor/demangle v0.0.0-20211126204342-3ad08eb09c01 h1:+0qIm4/XbPn2PYkj6QM6CX/FJN5DGvFOaMkSyB1xuh8= -github.com/ianlancetaylor/demangle v0.0.0-20211126204342-3ad08eb09c01/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/ianlancetaylor/demangle v0.0.0-20220203202831-b7f99f1dbc96 h1:OOB/uHFWWV4Ek3aRFgRaVwSw5IuQw4csg4mKF6fCbN4= +github.com/ianlancetaylor/demangle v0.0.0-20220203202831-b7f99f1dbc96/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -2276,8 +2277,9 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= diff --git a/pkg/symbol/addr2line/dwarf.go b/pkg/symbol/addr2line/dwarf.go index 49aca265cb3..0dc58243064 100644 --- a/pkg/symbol/addr2line/dwarf.go +++ b/pkg/symbol/addr2line/dwarf.go @@ -14,67 +14,40 @@ package addr2line import ( - "debug/dwarf" "errors" "fmt" - "io" - "sort" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/reader" "github.com/go-kit/log" "github.com/go-kit/log/level" pb "github.com/parca-dev/parca/gen/proto/go/parca/metastore/v1alpha1" - "github.com/parca-dev/parca/internal/go/debug/elf" "github.com/parca-dev/parca/pkg/metastore" "github.com/parca-dev/parca/pkg/symbol/demangle" + "github.com/parca-dev/parca/pkg/symbol/elfutils" ) var ErrLocationFailedBefore = errors.New("failed to symbolize location, attempts are exhausted") type DwarfLiner struct { - logger log.Logger - demangler *demangle.Demangler + logger log.Logger - mapping *pb.Mapping - data *dwarf.Data - lineEntries map[dwarf.Offset][]dwarf.LineEntry - subprograms map[dwarf.Offset][]*godwarf.Tree - abstractSubprograms map[dwarf.Offset]*dwarf.Entry + dbgFile elfutils.DebugInfoFile attemptThreshold int attempts map[uint64]int failed map[uint64]struct{} } -func DWARF(logger log.Logger, demangler *demangle.Demangler, attemptThreshold int, m *pb.Mapping, path string) (*DwarfLiner, error) { - // TODO(kakkoyun): Handle offset, start and limit for dynamically linked libraries. - //f, err := s.bu.Open(file, m.Start, m.Limit, m.Offset) - //if err != nil { - // return nil, fmt.Errorf("open object file: %w", err) - //} - f, err := elf.Open(path) +// DWARF is a symbolizer that uses DWARF debug info to symbolize addresses. +func DWARF(logger log.Logger, path string, m *pb.Mapping, demangler *demangle.Demangler, attemptThreshold int) (*DwarfLiner, error) { + dbgFile, err := elfutils.NewDebugInfoFile(path, m, demangler) if err != nil { - return nil, fmt.Errorf("failed to open elf: %w", err) - } - defer f.Close() - - data, err := f.DWARF() - if err != nil { - return nil, fmt.Errorf("failed to read DWARF data: %w", err) + return nil, err } return &DwarfLiner{ - logger: logger, - demangler: demangler, - - mapping: m, - data: data, - - lineEntries: map[dwarf.Offset][]dwarf.LineEntry{}, - subprograms: map[dwarf.Offset][]*godwarf.Tree{}, - abstractSubprograms: map[dwarf.Offset]*dwarf.Entry{}, + logger: logger, + dbgFile: dbgFile, attemptThreshold: attemptThreshold, attempts: map[uint64]int{}, @@ -82,81 +55,6 @@ func DWARF(logger log.Logger, demangler *demangle.Demangler, attemptThreshold in }, nil } -func (dl *DwarfLiner) ensureLookUpTablesBuilt(cu *dwarf.Entry) error { - if _, ok := dl.lineEntries[cu.Offset]; ok { - // Already created. - return nil - } - - // The reader is positioned at byte offset 0 in the DWARF “line” section. - lr, err := dl.data.LineReader(cu) - if err != nil { - return err - } - if lr == nil { - return errors.New("failed to initialize line reader") - } - - for { - le := dwarf.LineEntry{} - err := lr.Next(&le) - if err != nil { - break - } - if le.IsStmt { - dl.lineEntries[cu.Offset] = append(dl.lineEntries[cu.Offset], le) - } - } - - er := dl.data.Reader() - // The reader is positioned at byte offset of compile unit in the DWARF “info” section. - er.Seek(cu.Offset) - entry, err := er.Next() - if err != nil || entry == nil { - return errors.New("failed to read entry for compile unit") - } - - if entry.Tag != dwarf.TagCompileUnit { - return errors.New("failed to find entry for compile unit") - } - -outer: - for { - entry, err := er.Next() - if err != nil { - if err == io.EOF { - break - } - continue - } - if entry == nil { - break - } - if entry.Tag == dwarf.TagCompileUnit { - // Reached to another compile unit. - break - } - - if entry.Tag == dwarf.TagSubprogram { - for _, field := range entry.Field { - if field.Attr == dwarf.AttrInline { - dl.abstractSubprograms[entry.Offset] = entry - continue outer - } - } - - tr, err := godwarf.LoadTree(entry.Offset, dl.data, 0) - if err != nil { - return fmt.Errorf("failed to extract dwarf tree: %w", err) - } - - dl.subprograms[cu.Offset] = append(dl.subprograms[cu.Offset], tr) - } - } - - return nil -} - func (dl *DwarfLiner) PCToLines(addr uint64) (lines []metastore.LocationLine, err error) { // Check if we already attempt to symbolize this location and failed. if _, failedBefore := dl.failed[addr]; failedBefore { @@ -170,7 +68,7 @@ func (dl *DwarfLiner) PCToLines(addr uint64) (lines []metastore.LocationLine, er } }() - lines, err = dl.sourceLines(addr) + lines, err = dl.dbgFile.SourceLines(addr) if err != nil { return nil, dl.handleError(addr, err) } @@ -198,93 +96,3 @@ func (dl *DwarfLiner) handleError(addr uint64, err error) error { dl.attempts[addr] = 1 return err } - -func (dl *DwarfLiner) sourceLines(addr uint64) ([]metastore.LocationLine, error) { - // The reader is positioned at byte offset 0 in the DWARF “info” section. - er := dl.data.Reader() - cu, err := er.SeekPC(addr) - if err != nil { - return nil, err - } - if cu == nil { - return nil, errors.New("failed to find a corresponding dwarf entry for given address") - } - - if err := dl.ensureLookUpTablesBuilt(cu); err != nil { - return nil, err - } - - lines := []metastore.LocationLine{} - var tr *godwarf.Tree - for _, t := range dl.subprograms[cu.Offset] { - if t.ContainsPC(addr) { - tr = t - break - } - } - if tr == nil { - return lines, nil - } - - name := tr.Entry.Val(dwarf.AttrName).(string) - file, line := findLineInfo(dl.lineEntries[cu.Offset], tr.Ranges) - lines = append(lines, metastore.LocationLine{ - Line: line, - Function: dl.demangler.Demangle(&pb.Function{ - Name: name, - Filename: file, - }), - }) - - // If pc is 0 then all inlined calls will be returned. - for _, ch := range reader.InlineStack(tr, addr) { - var name string - if ch.Tag == dwarf.TagSubprogram { - name = tr.Entry.Val(dwarf.AttrName).(string) - } else { - abstractOrigin := dl.abstractSubprograms[ch.Entry.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset)] - name = getFunctionName(abstractOrigin) - } - - file, line := findLineInfo(dl.lineEntries[cu.Offset], ch.Ranges) - lines = append(lines, metastore.LocationLine{ - Line: line, - Function: dl.demangler.Demangle(&pb.Function{ - Name: name, - Filename: file, - }), - }) - } - - return lines, nil -} - -func findLineInfo(entries []dwarf.LineEntry, rg [][2]uint64) (string, int64) { - file := "?" - var line int64 - i := sort.Search(len(entries), func(i int) bool { - return entries[i].Address >= rg[0][0] - }) - if i >= len(entries) { - return file, line - } - - le := dwarf.LineEntry{} - pc := entries[i].Address - if rg[0][0] <= pc && pc < rg[0][1] { - le = entries[i] - return le.File.Name, int64(le.Line) - } - - return file, line -} - -func getFunctionName(entry *dwarf.Entry) string { - var name string - for _, field := range entry.Field { - if field.Attr == dwarf.AttrName { - name = field.Val.(string) - } - } - return name -} diff --git a/pkg/symbol/addr2line/go.go b/pkg/symbol/addr2line/go.go index 912c52d5404..a376a6e6ec8 100644 --- a/pkg/symbol/addr2line/go.go +++ b/pkg/symbol/addr2line/go.go @@ -52,6 +52,7 @@ func (gl *GoLiner) PCToLines(addr uint64) (lines []metastore.LocationLine, err e } }() + // TODO(kakkoyun): Do we need to consider the base address for any part of Go binaries? file, line, fn := gl.symtab.PCToLine(addr) name := "?" if fn != nil { @@ -61,7 +62,8 @@ func (gl *GoLiner) PCToLines(addr uint64) (lines []metastore.LocationLine, err e line = 0 } - // TODO(kakkoyun): Find a way to symbolize inline functions. + // TODO(kakkoyun): These lines miss the inline functions. + // - Find a way to symbolize inline functions. lines = append(lines, metastore.LocationLine{ Line: int64(line), Function: &pb.Function{ diff --git a/pkg/symbol/elfutils/debuginfofile.go b/pkg/symbol/elfutils/debuginfofile.go new file mode 100644 index 00000000000..5cb152494ba --- /dev/null +++ b/pkg/symbol/elfutils/debuginfofile.go @@ -0,0 +1,232 @@ +// Copyright 2022 The Parca Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package elfutils + +import ( + "debug/dwarf" + "debug/elf" + "errors" + "fmt" + "io" + "sort" + + "github.com/go-delve/delve/pkg/dwarf/godwarf" + "github.com/go-delve/delve/pkg/dwarf/reader" + + pb "github.com/parca-dev/parca/gen/proto/go/parca/metastore/v1alpha1" + "github.com/parca-dev/parca/pkg/metastore" + "github.com/parca-dev/parca/pkg/symbol/demangle" +) + +type DebugInfoFile interface { + // SourceLines returns the resolved source lines for a given address. + SourceLines(addr uint64) ([]metastore.LocationLine, error) +} + +type debugInfoFile struct { + demangler *demangle.Demangler + + debugData *dwarf.Data + lineEntries map[dwarf.Offset][]dwarf.LineEntry + subprograms map[dwarf.Offset][]*godwarf.Tree + abstractSubprograms map[dwarf.Offset]*dwarf.Entry +} + +// NewDebugInfoFile creates a new DebugInfoFile. +func NewDebugInfoFile(path string, m *pb.Mapping, demangler *demangle.Demangler) (DebugInfoFile, error) { + f, err := elf.Open(path) + if err != nil { + return nil, fmt.Errorf("failed to open elf: %w", err) + } + defer f.Close() + + debugData, err := f.DWARF() + if err != nil { + return nil, fmt.Errorf("failed to read DWARF data: %w", err) + } + + return &debugInfoFile{ + demangler: demangler, + + debugData: debugData, + lineEntries: make(map[dwarf.Offset][]dwarf.LineEntry), + subprograms: make(map[dwarf.Offset][]*godwarf.Tree), + abstractSubprograms: make(map[dwarf.Offset]*dwarf.Entry), + }, nil +} + +func (f *debugInfoFile) SourceLines(addr uint64) ([]metastore.LocationLine, error) { + // The reader is positioned at byte offset 0 in the DWARF “info” section. + er := f.debugData.Reader() + cu, err := er.SeekPC(addr) + if err != nil { + return nil, err + } + if cu == nil { + return nil, errors.New("failed to find a corresponding dwarf entry for given address") + } + + if err := f.ensureLookUpTablesBuilt(cu); err != nil { + return nil, err + } + + lines := []metastore.LocationLine{} + var tr *godwarf.Tree + for _, t := range f.subprograms[cu.Offset] { + if t.ContainsPC(addr) { + tr = t + break + } + } + if tr == nil { + return lines, nil + } + + name := tr.Entry.Val(dwarf.AttrName).(string) + file, line := findLineInfo(f.lineEntries[cu.Offset], tr.Ranges) + lines = append(lines, metastore.LocationLine{ + Line: line, + Function: f.demangler.Demangle(&pb.Function{ + Name: name, + Filename: file, + }), + }) + + // If pc is 0 then all inlined calls will be returned. + for _, ch := range reader.InlineStack(tr, addr) { + var name string + if ch.Tag == dwarf.TagSubprogram { + name = tr.Entry.Val(dwarf.AttrName).(string) + } else { + abstractOrigin := f.abstractSubprograms[ch.Entry.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset)] + name = getFunctionName(abstractOrigin) + } + + file, line := findLineInfo(f.lineEntries[cu.Offset], ch.Ranges) + lines = append(lines, metastore.LocationLine{ + Line: line, + Function: f.demangler.Demangle(&pb.Function{ + Name: name, + Filename: file, + }), + }) + } + + return lines, nil +} + +func (f *debugInfoFile) ensureLookUpTablesBuilt(cu *dwarf.Entry) error { + if _, ok := f.lineEntries[cu.Offset]; ok { + // Already created. + return nil + } + + // The reader is positioned at byte offset 0 in the DWARF “line” section. + lr, err := f.debugData.LineReader(cu) + if err != nil { + return err + } + if lr == nil { + return errors.New("failed to initialize line reader") + } + + for { + le := dwarf.LineEntry{} + err := lr.Next(&le) + if err != nil { + break + } + if le.IsStmt { + f.lineEntries[cu.Offset] = append(f.lineEntries[cu.Offset], le) + } + } + + er := f.debugData.Reader() + // The reader is positioned at byte offset of compile unit in the DWARF “info” section. + er.Seek(cu.Offset) + entry, err := er.Next() + if err != nil || entry == nil { + return errors.New("failed to read entry for compile unit") + } + + if entry.Tag != dwarf.TagCompileUnit { + return errors.New("failed to find entry for compile unit") + } + +outer: + for { + entry, err := er.Next() + if err != nil { + if err == io.EOF { + break + } + continue + } + if entry == nil { + break + } + if entry.Tag == dwarf.TagCompileUnit { + // Reached to another compile unit. + break + } + + if entry.Tag == dwarf.TagSubprogram { + for _, field := range entry.Field { + if field.Attr == dwarf.AttrInline { + f.abstractSubprograms[entry.Offset] = entry + continue outer + } + } + + tr, err := godwarf.LoadTree(entry.Offset, f.debugData, 0) + if err != nil { + return fmt.Errorf("failed to extract dwarf tree: %w", err) + } + + f.subprograms[cu.Offset] = append(f.subprograms[cu.Offset], tr) + } + } + + return nil +} + +func findLineInfo(entries []dwarf.LineEntry, rg [][2]uint64) (string, int64) { + file := "?" + var line int64 // 0 + i := sort.Search(len(entries), func(i int) bool { + return entries[i].Address >= rg[0][0] + }) + if i >= len(entries) { + return file, line + } + + le := dwarf.LineEntry{} + pc := entries[i].Address + if rg[0][0] <= pc && pc < rg[0][1] { + le = entries[i] + return le.File.Name, int64(le.Line) + } + + return file, line +} + +func getFunctionName(entry *dwarf.Entry) string { + var name string + for _, field := range entry.Field { + if field.Attr == dwarf.AttrName { + name = field.Val.(string) + } + } + return name +} diff --git a/pkg/symbol/elfutils/elfutils.go b/pkg/symbol/elfutils/elfutils.go index 99bb48b88a8..1adafc7149e 100644 --- a/pkg/symbol/elfutils/elfutils.go +++ b/pkg/symbol/elfutils/elfutils.go @@ -33,6 +33,7 @@ var dwarfSuffix = func(s *elf.Section) string { } } +// HasDWARF reports whether the specified executable or library file contains DWARF debug information. func HasDWARF(path string) (bool, error) { f, err := elf.Open(path) if err != nil { @@ -71,6 +72,7 @@ func readableDWARFSections(f *elf.File) (map[string]struct{}, error) { return exists, nil } +// IsSymbolizableGoObjFile checks whether the specified executable or library file is generated by Go toolchain. func IsSymbolizableGoObjFile(path string) (bool, error) { // Checks ".note.go.buildid" section and symtab better to keep those sections in object file. f, err := elf.Open(path) diff --git a/pkg/symbol/symbol.go b/pkg/symbol/symbol.go index 2f352ece9e2..fe9bbc40b7c 100644 --- a/pkg/symbol/symbol.go +++ b/pkg/symbol/symbol.go @@ -125,7 +125,7 @@ func (s *Symbolizer) newLiner(m *pb.Mapping, path string) (liner, error) { } if hasDWARF { level.Debug(s.logger).Log("msg", "using DWARF liner to resolve symbols", "file", path) - lnr, err := addr2line.DWARF(s.logger, s.demangler, s.attemptThreshold, m, path) + lnr, err := addr2line.DWARF(s.logger, path, m, s.demangler, s.attemptThreshold) if err != nil { level.Error(s.logger).Log( "msg", "failed to open object file",