Skip to content

Commit

Permalink
Add source command to build source archive from debuginfo
Browse files Browse the repository at this point in the history
  • Loading branch information
brancz committed Aug 31, 2023
1 parent ace8012 commit 0adf2c5
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 1 deletion.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,8 @@ Commands:
buildid <path>
Extract buildid.
source <debuginfo-path> [<out-path>]
Build a source archive by discovering files from a given debuginfo file.
Run "parca-debuginfo <command> --help" for more information on a command.
```
101 changes: 101 additions & 0 deletions cmd/parca-debuginfo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
package main

import (
"archive/tar"
"context"
"crypto/tls"
"debug/dwarf"
"debug/elf"
"errors"
"fmt"
Expand All @@ -28,6 +30,7 @@ import (
"github.com/alecthomas/kong"
"github.com/go-kit/log"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/klauspost/compress/zstd"
grun "github.com/oklog/run"
"github.com/parca-dev/parca-agent/pkg/buildid"
"github.com/parca-dev/parca-agent/pkg/debuginfo"
Expand Down Expand Up @@ -72,6 +75,11 @@ type flags struct {
Buildid struct {
Path string `kong:"required,arg,name='path',help='Paths to extract buildid.',type:'path'"`
} `cmd:"" help:"Extract buildid."`

Source struct {
DebuginfoPath string `kong:"required,arg,name='debuginfo-path',help='Path to debuginfo file',type:'path'"`
OutPath string `kong:"arg,name='out-path',help='Path to output archive file',type:'path',default='source.tar.zstd'"`
} `cmd:"" help:"Build a source archive by discovering files from a given debuginfo file."`
}

func main() {
Expand Down Expand Up @@ -335,6 +343,99 @@ func run(kongCtx *kong.Context, flags flags) error {
cancel()
})

case "source <debuginfo-path>":
g.Add(func() error {
f, err := elf.Open(flags.Source.DebuginfoPath)
if err != nil {
return fmt.Errorf("open elf: %w", err)
}
defer f.Close()

sf, err := os.Create(flags.Source.OutPath)
if err != nil {
return fmt.Errorf("create source archive: %w", err)
}
defer sf.Close()

zw, err := zstd.NewWriter(sf)
if err != nil {
return fmt.Errorf("create zstd writer: %w", err)
}

tw := tar.NewWriter(zw)

d, err := f.DWARF()
if err != nil {
return fmt.Errorf("get dwarf data: %w", err)
}

r := d.Reader()
seen := map[string]struct{}{}
for {
e, err := r.Next()
if err != nil {
return fmt.Errorf("read DWARF entry: %w", err)
}
if e == nil {
break
}

if e.Tag == dwarf.TagCompileUnit {
lr, err := d.LineReader(e)
if err != nil {
return fmt.Errorf("get line reader: %w", err)
}

if lr == nil {
continue
}

for _, lineFile := range lr.Files() {
if lineFile == nil {
continue
}
if _, ok := seen[lineFile.Name]; !ok {
sourceFile, err := os.Open(lineFile.Name)
if errors.Is(err, os.ErrNotExist) {
fmt.Fprintf(os.Stderr, "skipping file %q: does not exist\n", lineFile.Name)
seen[lineFile.Name] = struct{}{}
continue
}
if err != nil {
return fmt.Errorf("open file: %w", err)
}

stat, err := sourceFile.Stat()
if err != nil {
return fmt.Errorf("stat file: %w", err)
}

if err := tw.WriteHeader(&tar.Header{
Name: lineFile.Name,
Size: stat.Size(),
}); err != nil {
return fmt.Errorf("write tar header: %w", err)
}

if _, err = io.Copy(tw, sourceFile); err != nil {
return fmt.Errorf("copy file to tar: %w", err)
}

if err := sourceFile.Close(); err != nil {
return fmt.Errorf("close file: %w", err)
}

seen[lineFile.Name] = struct{}{}
}
}
}
}

return nil
}, func(error) {
cancel()
})

default:
cancel()
return errors.New("unknown command: " + kongCtx.Command())
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/alecthomas/kong v0.8.0
github.com/go-kit/log v0.2.1
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/klauspost/compress v1.16.7
github.com/oklog/run v1.1.0
github.com/parca-dev/parca v0.18.1-0.20230816074650-c9b9bed904c3
github.com/parca-dev/parca-agent v0.12.1-0.20230216133018-8dd5ccaeef0f
Expand Down Expand Up @@ -64,7 +65,6 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/huaweicloud/huaweicloud-sdk-go-obs v3.23.3+incompatible // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
Expand Down

0 comments on commit 0adf2c5

Please sign in to comment.