diff --git a/Makefile b/Makefile index f2a12fc..20d95c7 100644 --- a/Makefile +++ b/Makefile @@ -5,11 +5,12 @@ help: @echo '' @echo 'Here are the targets:' @echo '' - @echo 'To test : "make check"' + @echo 'To test : "make test"' @echo 'To develop : "make develop"' @echo 'To install : "make install"' @echo 'To format : "make format"' - @echo 'To lint : "make lint"' + @echo 'To vet : "make vet"' + @echo 'To staticcheck : "make check"' @echo 'To clean : "make clean"' @echo '' @@ -20,14 +21,17 @@ develop: go install github.com/SRI-CSL/gllvm/cmd/... -check: develop +test: develop go test -v ./tests format: gofmt -s -w shared/*.go tests/*.go cmd/*/*.go -lint: - golint ./shared/ ./tests/ ./cmd/... +check: + staticcheck ./... + +vet: + go vet ./... clean: rm -f data/*hello data/*.bc [td]*/.*.c.o [td]*/*.o [td]*/.*.c.o.bc data/*.notanextensionthatwerecognize diff --git a/shared/compiler.go b/shared/compiler.go index bf83ba7..3f604a2 100644 --- a/shared/compiler.go +++ b/shared/compiler.go @@ -35,7 +35,6 @@ package shared import ( "io" - "io/ioutil" "os" "path" "path/filepath" @@ -49,7 +48,7 @@ type bitcodeToObjectLink struct { objPath string } -//Compile wraps a call to the compiler with the given args. +// Compile wraps a call to the compiler with the given args. func Compile(args []string, compiler string) (exitCode int) { exitCode = 0 @@ -84,8 +83,8 @@ func Compile(args []string, compiler string) (exitCode int) { if compiler == "flang" { wg.Add(1) go execCompile(compilerExecName, pr, &wg, &ok) - wg.Wait(); - wg.Add(1); + wg.Wait() + wg.Add(1) go buildAndAttachBitcode(compilerExecName, pr, &bcObjLinks, &newObjectFiles, &wg) wg.Wait() } else { @@ -191,7 +190,7 @@ func injectPath(extension, bcFile, objFile string) (success bool) { // Store bitcode path to temp file var absBcPath, _ = filepath.Abs(bcFile) tmpContent := []byte(absBcPath + "\n") - tmpFile, err := ioutil.TempFile("", "gllvm") + tmpFile, err := os.CreateTemp("", "gllvm") if err != nil { LogError("attachBitcodePathToObject: %v\n", err) return @@ -313,10 +312,12 @@ func execCompile(compilerExecName string, pr ParserResult, wg *sync.WaitGroup, o // But for the now, we just remove forbidden arguments var success bool var err error + var linking = false // start afresh arguments := []string{} // we are linking rather than compiling if len(pr.InputFiles) == 0 && len(pr.LinkArgs) > 0 { + linking = true if pr.IsLTO { arguments = append(arguments, LLVMLtoLDFLAGS...) } @@ -338,6 +339,11 @@ func execCompile(compilerExecName string, pr ParserResult, wg *sync.WaitGroup, o } else { arguments = append(arguments, pr.InputList...) } + if linking { + LogInfo("LINKING with %v using %v", compilerExecName, arguments) + } else { + LogInfo("COMPILING with %v using %v", compilerExecName, arguments) + } LogDebug("Calling execCmd(%v, %v)", compilerExecName, arguments) success, err = execCmd(compilerExecName, arguments, "") if !success { @@ -346,41 +352,6 @@ func execCompile(compilerExecName string, pr ParserResult, wg *sync.WaitGroup, o } } -// Tries to build object file - -func oldExecCompile(compilerExecName string, pr ParserResult, wg *sync.WaitGroup, ok *bool) { - defer (*wg).Done() - //iam: strickly speaking we should do more work here depending on whether this is - // a compile only, a link only, or ... - // But for the now, we just remove forbidden arguments - var success bool - var err error - - if len(pr.ForbiddenFlags) > 0 { - filteredArgs := pr.InputList[:0] - for _, arg := range pr.InputList { - found := false - for _, bad := range pr.ForbiddenFlags { - if bad == arg { - found = true - break - } - } - if !found { - filteredArgs = append(filteredArgs, arg) - } - } - success, err = execCmd(compilerExecName, filteredArgs, "") - } else { - success, err = execCmd(compilerExecName, pr.InputList, "") - } - - if !success { - LogError("Failed to compile using given arguments:\n%v %v\nexit status: %v\n", compilerExecName, pr.InputList, err) - *ok = false - } -} - // GetCompilerExecName returns the full path of the executable func GetCompilerExecName(compiler string) string { switch compiler { @@ -405,7 +376,7 @@ func GetCompilerExecName(compiler string) string { } } -//CheckDefer is used to check the return values of defers +// CheckDefer is used to check the return values of defers func CheckDefer(f func() error) { if err := f(); err != nil { LogWarning("CheckDefer received error: %v\n", err) diff --git a/shared/environment.go b/shared/environment.go index 53969b9..b9a6992 100644 --- a/shared/environment.go +++ b/shared/environment.go @@ -50,49 +50,49 @@ const ( DarwinSectionName = "__llvm_bc" ) -//LLVMToolChainBinDir is the user configured directory holding the LLVM binary tools. +// LLVMToolChainBinDir is the user configured directory holding the LLVM binary tools. var LLVMToolChainBinDir string -//LLVMCCName is the user configured name of the clang compiler. +// LLVMCCName is the user configured name of the clang compiler. var LLVMCCName string -//LLVMCXXName is the user configured name of the clang++ compiler. +// LLVMCXXName is the user configured name of the clang++ compiler. var LLVMCXXName string -//LLVMFName is the user configered name of the flang compiler. +// LLVMFName is the user configered name of the flang compiler. var LLVMFName string -//LLVMARName is the user configured name of the llvm-ar. +// LLVMARName is the user configured name of the llvm-ar. var LLVMARName string -//LLVMLINKName is the user configured name of the llvm-link. +// LLVMLINKName is the user configured name of the llvm-link. var LLVMLINKName string -//LLVMLINKFlags is the user configured list of flags to append to llvm-link. +// LLVMLINKFlags is the user configured list of flags to append to llvm-link. var LLVMLINKFlags []string -//LLVMConfigureOnly is the user configured flag indicating a single pass mode is required. +// LLVMConfigureOnly is the user configured flag indicating a single pass mode is required. var LLVMConfigureOnly string -//LLVMBitcodeStorePath is the user configured location of the bitcode archive. +// LLVMBitcodeStorePath is the user configured location of the bitcode archive. var LLVMBitcodeStorePath string -//LLVMLoggingLevel is the user configured logging level: ERROR, WARNING, INFO, DEBUG. +// LLVMLoggingLevel is the user configured logging level: ERROR, WARNING, INFO, DEBUG. var LLVMLoggingLevel string -//LLVMLoggingFile is the path to the optional logfile (useful when configuring) +// LLVMLoggingFile is the path to the optional logfile (useful when configuring) var LLVMLoggingFile string -//LLVMObjcopy is the path to the objcopy executable used to attach the bitcode on *nix. +// LLVMObjcopy is the path to the objcopy executable used to attach the bitcode on *nix. var LLVMObjcopy string -//LLVMLd is the path to the ld executable used to attach the bitcode on OSX. +// LLVMLd is the path to the ld executable used to attach the bitcode on OSX. var LLVMLd string -//LLVMbcGen is the list of args to pass to clang during the bitcode generation step. +// LLVMbcGen is the list of args to pass to clang during the bitcode generation step. var LLVMbcGen []string -//LLVMLtoLDFLAGS is the list of extra flags to pass to the linking steps, when under -flto +// LLVMLtoLDFLAGS is the list of extra flags to pass to the linking steps, when under -flto var LLVMLtoLDFLAGS []string const ( diff --git a/shared/extractor.go b/shared/extractor.go index adbf743..501f464 100644 --- a/shared/extractor.go +++ b/shared/extractor.go @@ -39,7 +39,6 @@ import ( "debug/macho" "flag" "fmt" - "io/ioutil" "os" "os/exec" "path" @@ -50,7 +49,7 @@ import ( "strings" ) -//ExtractionArgs encapsulate the results of parsing the commandline options +// ExtractionArgs encapsulate the results of parsing the commandline options type ExtractionArgs struct { Failure bool // indicates failure in parsing the cmd line args Verbose bool // inform the user of what is going on @@ -71,7 +70,7 @@ type ExtractionArgs struct { Extractor func(string) ([]string, bool) } -//for printing out the parsed arguments, some have been skipped. +// for printing out the parsed arguments, some have been skipped. func (ea ExtractionArgs) String() string { format := ` @@ -93,7 +92,7 @@ ea.StrictExtract: %v ea.LlvmLinkerName, ea.ArchiverName, ea.StrictExtract) } -//ParseSwitches parses the command line into an ExtractionArgs object. +// ParseSwitches parses the command line into an ExtractionArgs object. func ParseSwitches(args []string) (ea ExtractionArgs) { var flagSet *flag.FlagSet = flag.NewFlagSet(args[0], flag.ContinueOnError) @@ -145,7 +144,7 @@ func ParseSwitches(args []string) (ea ExtractionArgs) { return } -//Extract extracts the LLVM bitcode according to the arguments it is passed. +// Extract extracts the LLVM bitcode according to the arguments it is passed. func Extract(args []string) (exitCode int) { exitCode = 1 @@ -443,20 +442,20 @@ func extractFiles(ea ExtractionArgs, inputFile string, toc map[string]int) (succ return } -//handleArchive processes an archive, and creates either a bitcode archive, or a module, depending on the flags used. +// handleArchive processes an archive, and creates either a bitcode archive, or a module, depending on the flags used. // -// Archives are strange beasts. handleArchive processes the archive by: +// Archives are strange beasts. handleArchive processes the archive by: // -// 1. first creating a table of contents of the archive, which maps file names (in the archive) to the number of -// times a file with that name is stored in the archive. +// 1. first creating a table of contents of the archive, which maps file names (in the archive) to the number of +// times a file with that name is stored in the archive. // -// 2. for each OCCURRENCE of a file (name and count) it extracts the section from the object file, and adds the -// bitcode paths to the bitcode list. +// 2. for each OCCURRENCE of a file (name and count) it extracts the section from the object file, and adds the +// bitcode paths to the bitcode list. // -// 3. it then either links all these bitcode files together using llvm-link, or else is creates a bitcode -// archive using llvm-ar +// 3. it then either links all these bitcode files together using llvm-link, or else is creates a bitcode +// archive using llvm-ar // -//iam: 5/1/2018 +// iam: 5/1/2018 func handleArchive(ea ExtractionArgs) (success bool) { // List bitcode files to link var bcFiles []string @@ -467,7 +466,7 @@ func handleArchive(ea ExtractionArgs) (success bool) { LogInfo("handleArchive: ExtractionArgs = %v\n", ea) // Create tmp dir - tmpDirName, err := ioutil.TempDir("", "gllvm") + tmpDirName, err := os.MkdirTemp("", "gllvm") if err != nil { LogError("The temporary directory in which to extract object files could not be created.") return @@ -607,7 +606,7 @@ func fetchArgMax(ea ExtractionArgs) (argMax int) { func linkBitcodeFilesIncrementally(ea ExtractionArgs, filesToLink []string, argMax int, linkArgs []string) (success bool) { var tmpFileList []string // Create tmp dir - tmpDirName, err := ioutil.TempDir(".", "glinking") + tmpDirName, err := os.MkdirTemp(".", "glinking") if err != nil { LogError("The temporary directory in which to put temporary linking files could not be created.") return @@ -619,7 +618,7 @@ func linkBitcodeFilesIncrementally(ea ExtractionArgs, filesToLink []string, argM LogInfo("Keeping the temporary folder") } - tmpFile, err := ioutil.TempFile(tmpDirName, "tmp") + tmpFile, err := os.CreateTemp(tmpDirName, "tmp") if err != nil { LogError("The temporary linking file could not be created.") return @@ -643,7 +642,7 @@ func linkBitcodeFilesIncrementally(ea ExtractionArgs, filesToLink []string, argM if ea.Verbose { linkArgs = append(linkArgs, "-v") } - tmpFile, err = ioutil.TempFile(tmpDirName, "tmp") + tmpFile, err = os.CreateTemp(tmpDirName, "tmp") if err != nil { LogError("Could not generate a temp file in %s because %v.\n", tmpDirName, err) success = false @@ -778,13 +777,13 @@ func writeManifest(ea ExtractionArgs, bcFiles []string, artifactFiles []string) section1 := "Physical location of extracted files:\n" + strings.Join(bcFiles, "\n") + "\n\n" section2 := "Build-time location of extracted files:\n" + strings.Join(artifactFiles, "\n") contents := []byte(section1 + section2) - if err := ioutil.WriteFile(manifestFilename, contents, 0644); err != nil { + if err := os.WriteFile(manifestFilename, contents, 0644); err != nil { LogError("There was an error while writing the manifest file: ", err) return } } else { contents := []byte("\n" + strings.Join(bcFiles, "\n") + "\n") - if err := ioutil.WriteFile(manifestFilename, contents, 0644); err != nil { + if err := os.WriteFile(manifestFilename, contents, 0644); err != nil { LogError("There was an error while writing the manifest file: ", err) return } diff --git a/shared/filetypes.go b/shared/filetypes.go index ef9167e..3dcbb6f 100644 --- a/shared/filetypes.go +++ b/shared/filetypes.go @@ -195,7 +195,7 @@ func MachoFileType(objectFile string) (code BinaryType, err error) { return } -//IsObjectFileForOS returns true if the given file is an object file for the given OS, using the debug/elf and debug/macho packages. +// IsObjectFileForOS returns true if the given file is an object file for the given OS, using the debug/elf and debug/macho packages. func IsObjectFileForOS(objectFile string, operatingSys string) (ok bool, err error) { plain := IsPlainFile(objectFile) if !plain { @@ -231,7 +231,7 @@ const ( fileTypeERROR ) -//iam: this is not that robust, because it depends on the file utility "file" which is +// iam: this is not that robust, because it depends on the file utility "file" which is // often missing on docker images (the klee docker file had this problem) // this is only used in extraction, not in compilation. func getFileType(realPath string) (fileType int, err error) { diff --git a/shared/logging.go b/shared/logging.go index 9c2c0aa..ba2e3df 100644 --- a/shared/logging.go +++ b/shared/logging.go @@ -46,7 +46,7 @@ const ( debugV ) -//loggingLevels is the accepted logging levels. +// loggingLevels is the accepted logging levels. var loggingLevels = map[string]int{ "ERROR": errorV, "WARNING": warningV, @@ -61,10 +61,10 @@ var loggingPrefixes = map[int]string{ debugV: "DEBUG:", } -//loggingLevel is the user configured level of logging: ERROR, WARNING, INFO, DEBUG +// loggingLevel is the user configured level of logging: ERROR, WARNING, INFO, DEBUG var loggingLevel = warningV -//loggingFilePointer is where the logging is streamed too. +// loggingFilePointer is where the logging is streamed too. var loggingFilePointer = os.Stderr func init() { @@ -105,19 +105,19 @@ func makeLogger(lvl int) func(format string, a ...interface{}) { } } -//LogDebug logs to the configured stream if the logging level is DEBUG. +// LogDebug logs to the configured stream if the logging level is DEBUG. var LogDebug = makeLogger(debugV) -//LogInfo logs to the configured stream if the logging level is INFO or lower. +// LogInfo logs to the configured stream if the logging level is INFO or lower. var LogInfo = makeLogger(infoV) -//LogWarning logs to the configured stream if the logging level is WARNING or lower. +// LogWarning logs to the configured stream if the logging level is WARNING or lower. var LogWarning = makeLogger(warningV) -//LogError logs to the configured stream if the logging level is ERROR or lower. +// LogError logs to the configured stream if the logging level is ERROR or lower. var LogError = makeLogger(errorV) -//LogWrite writes to the logging stream, irregardless of levels. +// LogWrite writes to the logging stream, irregardless of levels. var LogWrite = makeLogger(-1) func informUser(format string, a ...interface{}) { diff --git a/shared/parser.go b/shared/parser.go index 5a280fe..ac098fa 100644 --- a/shared/parser.go +++ b/shared/parser.go @@ -44,7 +44,7 @@ import ( "strings" ) -//ParserResult is the result of parsing and partioning the command line arguments. +// ParserResult is the result of parsing and partioning the command line arguments. type ParserResult struct { InputList []string InputFiles []string @@ -113,7 +113,7 @@ type argPattern struct { finfo flagInfo } -//SkipBitcodeGeneration indicates whether or not we should generate bitcode for these command line options. +// SkipBitcodeGeneration indicates whether or not we should generate bitcode for these command line options. func (pr *ParserResult) SkipBitcodeGeneration() bool { reason := "No particular reason" retval := false @@ -155,7 +155,7 @@ func (pr *ParserResult) SkipBitcodeGeneration() bool { return retval } -//Parse analyzes the command line aruguments and returns the result of that analysis. +// Parse analyzes the command line aruguments and returns the result of that analysis. func Parse(argList []string) ParserResult { var pr = ParserResult{} pr.InputList = argList diff --git a/shared/sanity.go b/shared/sanity.go index e2bd6dc..c32d1a9 100644 --- a/shared/sanity.go +++ b/shared/sanity.go @@ -102,13 +102,12 @@ type sanityArgs struct { // SanityCheck performs the environmental sanity check. // -// Performs the following checks in order: -// 0. Check the logging -// 1. Check that the OS is supported. -// 2. Checks that the compiler settings make sense. -// 3. Checks that the needed LLVM utilities exists. -// 4. Check that the store, if set, exists. -// +// Performs the following checks in order: +// 0. Check the logging +// 1. Check that the OS is supported. +// 2. Checks that the compiler settings make sense. +// 3. Checks that the needed LLVM utilities exists. +// 4. Check that the store, if set, exists. func SanityCheck() { sa := parseSanitySwitches()