Skip to content

Commit

Permalink
Merge pull request #291 from kakkoyun/fix_debuginfo_find
Browse files Browse the repository at this point in the history
Fix local debuginfo file discovery
  • Loading branch information
kakkoyun committed Mar 18, 2022
2 parents 5c3ea8c + e92a9f6 commit 7d76f76
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 37 deletions.
6 changes: 3 additions & 3 deletions cmd/debug-info/main.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2021 The Parca Authors
// Copyright (c) 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
Expand All @@ -10,6 +10,7 @@
// 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 main

Expand Down Expand Up @@ -160,12 +161,11 @@ func main() {
})
case "buildid <path>":
g.Add(func() error {
buildID, err := buildid.BuildID(flags.Buildid.Path)
_, err := buildid.BuildID(flags.Buildid.Path)
if err != nil {
level.Error(logger).Log("msg", "failed to extract elf build ID", "err", err)
return err
}
fmt.Println(buildID)
return nil
}, func(error) {
cancel()
Expand Down
1 change: 1 addition & 0 deletions deploy/dev.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ function(serverVersion='v0.4.2')
logLevel: 'debug',
insecure: true,
insecureSkipVerify: true,
// debugInfoDisable: true,
tempDir: '/tmp',
// podLabelSelector: 'app.kubernetes.io/name=parca',
});
Expand Down
56 changes: 22 additions & 34 deletions pkg/debuginfo/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,20 @@ import (
"context"
"errors"
"fmt"
"io/fs"
"os"
"path"
"path/filepath"
"strings"

"github.com/go-kit/log"
"github.com/goburrow/cache"

"github.com/parca-dev/parca-agent/pkg/buildid"
)

type realfs struct{}

func (f *realfs) Open(name string) (fs.File, error) { return os.Open(name) }

var fileSystem fs.FS = &realfs{}

// Finder finds the additional debug information on the system.
type Finder struct {
logger log.Logger
Expand Down Expand Up @@ -77,38 +80,23 @@ func (f *Finder) Find(ctx context.Context, buildID, root string) (string, error)
}

func find(buildID, root string) (string, error) {
var (
found = false
file string
)
// TODO(kakkoyun): Distros may have different locations for debuginfo files.
// Add support for all of them. Add an issue fir this.
err := filepath.Walk(path.Join(root, "/usr/lib/debug"), func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
id, err := buildid.BuildID(path)
if err != nil {
return fmt.Errorf("failed to extract elf build ID, %w", err)
}
if strings.EqualFold(id, buildID) {
found = true
file = path
}
}
return nil
})
if err != nil {
if os.IsNotExist(err) {
return "", errNotFound
}

return "", fmt.Errorf("failed to walk debug files: %w", err)
if len(buildID) < 2 {
return "", errors.New("invalid build ID")
}
// Debian: /usr/lib/debug/.build-id/f9/02f8a561c3abdb9c8d8c859d4243bd8c3f928f.debug
// -- apt install <package>-dbg
// Fedora: /usr/lib/debug/.build-id/da/40581445b62eff074d67fae906792cb26e8d54.debug
// -- dnf --enablerepo=fedora-debuginfo --enablerepo=updates-debuginfo install <package>-debuginfo
// Arch: https://wiki.archlinux.org/title/Debugging/Getting_traces
file := filepath.Join(root, "/usr/lib/debug", ".build-id", buildID[:2], buildID[2:]) + ".debug"
_, err := fs.Stat(fileSystem, file)
if err == nil {
return file, nil
}

if !found {
if os.IsNotExist(err) {
return "", errNotFound
}
return file, nil

return "", fmt.Errorf("failed to search debug files: %w", err)
}
74 changes: 74 additions & 0 deletions pkg/debuginfo/find_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) 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 debuginfo

import (
"testing"

"github.com/parca-dev/parca-agent/pkg/testutil"
)

func Test_find(t *testing.T) {
oldFs := fileSystem
mfs := testutil.NewFakeFS(map[string][]byte{
"/proc/124/root/usr/lib/debug/.build-id/d1/b25b63b3edc63832fd885e4b997f8a463ea573.debug": []byte("whatever"),
})
fileSystem = mfs
t.Cleanup(func() {
fileSystem = oldFs
})

type args struct {
buildID string
root string
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "empty",
args: args{
buildID: "",
root: "",
},
want: "",
wantErr: true,
},
{
name: "valid",
args: args{
buildID: "d1b25b63b3edc63832fd885e4b997f8a463ea573",
root: "/proc/124/root",
},
want: "/proc/124/root/usr/lib/debug/.build-id/d1/b25b63b3edc63832fd885e4b997f8a463ea573.debug",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := find(tt.args.buildID, tt.args.root)
if (err != nil) != tt.wantErr {
t.Errorf("find() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("find() got = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit 7d76f76

Please sign in to comment.