├── README.md ├── LICENSE ├── main.go └── dwarf.go /README.md: -------------------------------------------------------------------------------- 1 | **Deprecated**: `gorebuild` does not support Go modules, and the need to update the built-in default GOROOT has mostly gone away, in favor of using [`go/packages`](https://pkg.go.dev/golang.org/x/tools/go/packages) which invokes the go tool from `$PATH`. 2 | 3 | `gorebuild` uses symbol tables to figure out the import path of a Go binary, re-installs it. 4 | 5 | This is useful for example when changing GOROOT (for example updating Go with Homebrew), since the default GOROOT is embedded in the binary and it's critical for some static analysis tools. 6 | 7 | Installation: `go get -u github.com/FiloSottile/gorebuild` 8 | 9 | Usage: `gorebuild [-n] [binary ...]` 10 | 11 | If invoked with `-n` it will only print the import paths. 12 | 13 | If invoked without any arguments, it runs on all files in `$GOPATH/bin`. 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Filippo Valsorda 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "go/build" 7 | "io/ioutil" 8 | "log" 9 | "os" 10 | "os/exec" 11 | "path/filepath" 12 | "strings" 13 | ) 14 | 15 | func main() { 16 | dry := flag.Bool("n", false, "don't build, just print the package names") 17 | flag.Parse() 18 | 19 | bins := flag.Args() 20 | if len(bins) == 0 { 21 | fi, err := ioutil.ReadDir(build.Default.GOPATH + "/bin") 22 | if err != nil { 23 | log.Fatal(err) 24 | } 25 | for _, f := range fi { 26 | if f.IsDir() { 27 | continue 28 | } 29 | bins = append(bins, build.Default.GOPATH+"/bin/"+f.Name()) 30 | } 31 | } 32 | 33 | var binDir string 34 | if !*dry { 35 | dir, err := ioutil.TempDir("", "gorebuild") 36 | if err != nil { 37 | log.Fatal(err) 38 | } 39 | defer os.RemoveAll(dir) 40 | binDir = dir 41 | } 42 | 43 | for _, file := range bins { 44 | path, err := getMainPath(file) 45 | if err != nil { 46 | log.Printf("Skipping %s: %s", file, err) 47 | continue 48 | } 49 | importPath := stripPath(path) 50 | if *dry { 51 | fmt.Println(stripPath(path)) 52 | } else { 53 | cmd := exec.Command("go", "install", "-v", importPath) 54 | cmd.Env = append(os.Environ(), "GOBIN="+binDir) 55 | cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr 56 | cmd.Run() 57 | fi, err := ioutil.ReadDir(binDir) 58 | if err != nil { 59 | log.Fatal(err) 60 | } 61 | for _, f := range fi { 62 | err := os.Rename(filepath.Join(binDir, f.Name()), build.Default.GOPATH+"/bin/"+f.Name()) 63 | if err != nil { 64 | log.Fatal(err) 65 | } 66 | } 67 | } 68 | } 69 | } 70 | 71 | func stripPath(path string) string { 72 | dir := filepath.Dir(path) 73 | return strings.TrimPrefix(dir, build.Default.GOPATH+"/src/") 74 | } 75 | -------------------------------------------------------------------------------- /dwarf.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "debug/elf" 5 | "debug/gosym" 6 | "debug/macho" 7 | "errors" 8 | "os" 9 | ) 10 | 11 | func getTable(file string) (*gosym.Table, error) { 12 | f, err := os.Open(file) 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | var textStart uint64 18 | var symtab, pclntab []byte 19 | 20 | obj, err := elf.NewFile(f) 21 | if err == nil { 22 | if sect := obj.Section(".text"); sect == nil { 23 | return nil, errors.New("empty .text") 24 | } else { 25 | textStart = sect.Addr 26 | } 27 | if sect := obj.Section(".gosymtab"); sect != nil { 28 | if symtab, err = sect.Data(); err != nil { 29 | return nil, err 30 | } 31 | } 32 | if sect := obj.Section(".gopclntab"); sect != nil { 33 | if pclntab, err = sect.Data(); err != nil { 34 | return nil, err 35 | } 36 | } else { 37 | return nil, errors.New("empty .gopclntab") 38 | } 39 | 40 | } else { 41 | obj, err := macho.NewFile(f) 42 | if err != nil { 43 | return nil, err 44 | } 45 | 46 | if sect := obj.Section("__text"); sect == nil { 47 | return nil, errors.New("empty __text") 48 | } else { 49 | textStart = sect.Addr 50 | } 51 | if sect := obj.Section("__gosymtab"); sect != nil { 52 | if symtab, err = sect.Data(); err != nil { 53 | return nil, err 54 | } 55 | } 56 | if sect := obj.Section("__gopclntab"); sect != nil { 57 | if pclntab, err = sect.Data(); err != nil { 58 | return nil, err 59 | } 60 | } else { 61 | return nil, errors.New("empty __gopclntab") 62 | } 63 | } 64 | 65 | pcln := gosym.NewLineTable(pclntab, textStart) 66 | return gosym.NewTable(symtab, pcln) 67 | } 68 | 69 | func getMainPath(file string) (string, error) { 70 | table, err := getTable(file) 71 | if err != nil { 72 | return "", err 73 | } 74 | path, _, _ := table.PCToLine(table.LookupFunc("main.main").Entry) 75 | return path, nil 76 | } 77 | --------------------------------------------------------------------------------