This repository was archived by the owner on Jan 5, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 126
Build tracing #324
Merged
Merged
Build tracing #324
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
1679652
Add package directory as a wanted root
eaf5342
Enable Go modules while determining module directory
2da89c6
extractor: factor out `run` from autobuilder
cd63ea8
extractor: revamp argument parsing
de0582a
autobuilder: extract out attempted build commands
85c9225
Add a new binary for tracing
3addb96
Add change note for build tracing
3c6626c
Don't trace through problem binaries on OS X
25eebe9
autobuilder: Clarify error message
e5afd1d
go-extractor: clarify --mimic error message
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| lgtm,codescanning | ||
| * The Go extractor now supports build tracing, allowing users to supply a build command when | ||
| creating databases with the CodeQL CLI or via configuration. It currently only supports projects | ||
| that use Go modules. To opt-in, set the environment variable `CODEQL_EXTRACTOR_GO_BUILD_TRACING` | ||
| to `on`, or supply a build command. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| **/go-autobuilder: | ||
| order compiler | ||
| trace no | ||
| **/go: | ||
| invoke ${config_dir}/go-extractor | ||
| prepend --mimic | ||
| prepend "${compiler}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| **/go-autobuilder: | ||
| order compiler | ||
| trace no | ||
| **/go: | ||
| invoke ${config_dir}/go-extractor | ||
| prepend --mimic | ||
| prepend "${compiler}" | ||
| /usr/bin/codesign: | ||
| replace yes | ||
| invoke /usr/bin/env | ||
| prepend /usr/bin/codesign | ||
| trace no | ||
| /usr/bin/pkill: | ||
| replace yes | ||
| invoke /usr/bin/env | ||
| prepend /usr/bin/pkill | ||
| trace no | ||
| /usr/bin/pgrep: | ||
| replace yes | ||
| invoke /usr/bin/env | ||
| prepend /usr/bin/pgrep | ||
| trace no |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| **/go-autobuilder.exe: | ||
| order compiler | ||
| trace no | ||
| **/go.exe: | ||
| invoke ${config_dir}/go-extractor.exe | ||
| prepend --mimic | ||
| prepend "${compiler}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| // Package autobuilder implements a simple system that attempts to run build commands for common | ||
| // build frameworks, if the relevant files exist. | ||
| package autobuilder | ||
|
|
||
| import ( | ||
| "log" | ||
| "os" | ||
| "os/exec" | ||
|
|
||
| "github.com/github/codeql-go/extractor/util" | ||
| ) | ||
|
|
||
| // CheckExtracted sets whether the autobuilder should check whether source files have been extracted | ||
| // to the CodeQL source directory as well as whether the build command executed successfully. | ||
| var CheckExtracted = false | ||
max-schaefer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // checkEmpty checks whether a directory either doesn't exist or is empty. | ||
| func checkEmpty(dir string) (bool, error) { | ||
| if !util.DirExists(dir) { | ||
| return true, nil | ||
| } | ||
|
|
||
| d, err := os.Open(dir) | ||
| if err != nil { | ||
| return false, err | ||
| } | ||
| defer d.Close() | ||
|
|
||
| names, err := d.Readdirnames(-1) | ||
| if err != nil { | ||
| return false, err | ||
| } | ||
| return len(names) == 0, nil | ||
| } | ||
|
|
||
| // checkExtractorRun checks whether the CodeQL Go extractor has run, by checking if the source | ||
| // archive directory is empty or not. | ||
| func checkExtractorRun() bool { | ||
| srcDir := os.Getenv("CODEQL_EXTRACTOR_GO_SOURCE_ARCHIVE_DIR") | ||
| if srcDir != "" { | ||
| empty, err := checkEmpty(srcDir) | ||
| if err != nil { | ||
| log.Fatalf("Unable to read source archive directory %s.", srcDir) | ||
| } | ||
| if empty { | ||
| log.Printf("No Go code seen; continuing to try other builds.") | ||
| return false | ||
| } | ||
| return true | ||
| } else { | ||
| log.Fatalf("No source directory set.\nThis binary should not be run manually; instead, use the CodeQL CLI or VSCode extension. See https://securitylab.github.com/tools/codeql.") | ||
| return false | ||
| } | ||
| } | ||
|
|
||
| // tryBuildIfExists tries to run the command `cmd args...` if the file `buildFile` exists and is not | ||
| // a directory. Returns true if the command was successful and false if not. | ||
| func tryBuildIfExists(buildFile, cmd string, args ...string) bool { | ||
| if util.FileExists(buildFile) { | ||
| log.Printf("%s found.\n", buildFile) | ||
| return tryBuild(cmd, args...) | ||
| } | ||
| return false | ||
max-schaefer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| // tryBuild tries to run `cmd args...`, returning true if successful and false if not. | ||
| func tryBuild(cmd string, args ...string) bool { | ||
| log.Printf("Trying build command %s %v", cmd, args) | ||
| res := util.RunCmd(exec.Command(cmd, args...)) | ||
| return res && (!CheckExtracted || checkExtractorRun()) | ||
| } | ||
|
|
||
| // Autobuild attempts to detect build system and run the corresponding command. | ||
| func Autobuild() bool { | ||
| return tryBuildIfExists("Makefile", "make") || | ||
| tryBuildIfExists("makefile", "make") || | ||
| tryBuildIfExists("GNUmakefile", "make") || | ||
| tryBuildIfExists("build.ninja", "ninja") || | ||
| tryBuildIfExists("build", "./build") || | ||
| tryBuildIfExists("build.sh", "./build.sh") | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "github.com/github/codeql-go/extractor/util" | ||
| "log" | ||
| "os" | ||
| "os/exec" | ||
| "path/filepath" | ||
| "runtime" | ||
|
|
||
| "github.com/github/codeql-go/extractor/autobuilder" | ||
| ) | ||
|
|
||
| func main() { | ||
| // check if a build command has successfully extracted something | ||
| autobuilder.CheckExtracted = true | ||
| if autobuilder.Autobuild() { | ||
| return | ||
| } | ||
|
|
||
| // if the autobuilder fails, invoke the extractor manually | ||
| // we cannot simply call `go build` here, because the tracer is not able to trace calls made by | ||
| // this binary | ||
| log.Printf("No build commands succeeded, falling back to go build ./...") | ||
|
|
||
| mypath, err := os.Executable() | ||
| if err != nil { | ||
| log.Fatalf("Could not determine path of extractor: %v.\n", err) | ||
| } | ||
| extractor := filepath.Join(filepath.Dir(mypath), "go-extractor") | ||
| if runtime.GOOS == "windows" { | ||
| extractor = extractor + ".exe" | ||
| } | ||
|
|
||
| util.RunCmd(exec.Command(extractor, "./...")) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,23 +20,70 @@ func usage() { | |
| fmt.Fprintf(os.Stderr, "--help Print this help.\n") | ||
| } | ||
|
|
||
| func parseFlags(args []string) ([]string, []string) { | ||
| func parseFlags(args []string, mimic bool) ([]string, []string) { | ||
| i := 0 | ||
| buildFlags := []string{} | ||
| for i < len(args) && strings.HasPrefix(args[i], "-") { | ||
| for ; i < len(args) && strings.HasPrefix(args[i], "-"); i++ { | ||
| if args[i] == "--" { | ||
| i++ | ||
| break | ||
| } | ||
|
|
||
| if args[i] == "--help" { | ||
| usage() | ||
| os.Exit(0) | ||
| } else { | ||
| buildFlags = append(buildFlags, args[i]) | ||
| if !mimic { | ||
| // we're not in mimic mode, try to parse our arguments | ||
| switch args[i] { | ||
| case "--help": | ||
| usage() | ||
| os.Exit(0) | ||
| case "--mimic": | ||
| if i+1 < len(args) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Worth printing a warning if this isn't true, since the command argument is required
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Except this one looks real |
||
| i++ | ||
| compiler := args[i] | ||
| log.Printf("Compiler: %s", compiler) | ||
| if i+1 < len(args) { | ||
| i++ | ||
| command := args[i] | ||
| if command == "build" || command == "install" || command == "run" { | ||
| log.Printf("Intercepting build") | ||
| return parseFlags(args[i+1:], true) | ||
| } else { | ||
| log.Printf("Non-build command '%s'; skipping", strings.Join(args[1:], " ")) | ||
| os.Exit(0) | ||
| } | ||
| } else { | ||
| log.Printf("Non-build command '%s'; skipping", strings.Join(args[1:], " ")) | ||
| os.Exit(0) | ||
| } | ||
| } else { | ||
| log.Fatalf("--mimic requires an argument, e.g. --mimic go") | ||
| } | ||
| } | ||
| } | ||
|
|
||
| i++ | ||
| // parse go build flags | ||
| switch args[i] { | ||
| // skip `-o output` and `-i`, if applicable | ||
| case "-o": | ||
| if i+1 < len(args) { | ||
| i++ | ||
| } | ||
| case "-i": | ||
| case "-p", "-asmflags", "-buildmode", "-compiler", "-gccgoflags", "-gcflags", "-installsuffix", | ||
| "-ldflags", "-mod", "-modfile", "-pkgdir", "-tags", "-toolexec": | ||
| if i+1 < len(args) { | ||
| buildFlags = append(buildFlags, args[i], args[i+1]) | ||
| i++ | ||
| } else { | ||
| buildFlags = append(buildFlags, args[i]) | ||
| } | ||
| default: | ||
| if strings.HasPrefix(args[i], "-") { | ||
| buildFlags = append(buildFlags, args[i]) | ||
| } else { | ||
| // stop parsing if the argument is not a flag (and so is positional) | ||
| break | ||
| } | ||
| } | ||
| } | ||
|
|
||
| cpuprofile = os.Getenv("CODEQL_EXTRACTOR_GO_CPU_PROFILE") | ||
|
|
@@ -46,7 +93,7 @@ func parseFlags(args []string) ([]string, []string) { | |
| } | ||
|
|
||
| func main() { | ||
| buildFlags, patterns := parseFlags(os.Args[1:]) | ||
| buildFlags, patterns := parseFlags(os.Args[1:], false) | ||
|
|
||
| if cpuprofile != "" { | ||
| f, err := os.Create(cpuprofile) | ||
|
|
@@ -63,9 +110,10 @@ func main() { | |
| if len(patterns) == 0 { | ||
| log.Println("Nothing to extract.") | ||
| } else { | ||
| log.Printf("Build flags: '%s'; patterns: '%s'\n", strings.Join(buildFlags, " "), strings.Join(patterns, " ")) | ||
| err := extractor.ExtractWithFlags(buildFlags, patterns) | ||
| if err != nil { | ||
| log.Fatal(err) | ||
| log.Fatalf("Error running go tooling: %s\n", err.Error()) | ||
| } | ||
| } | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.