Dusting away the bitrot, plus adding a COMPILING and LINKING line in the INFO log.

This commit is contained in:
Ian A. Mason 2022-09-06 16:54:43 -07:00
parent 48db30df93
commit 65d0c8c002
8 changed files with 74 additions and 101 deletions

View File

@ -5,11 +5,12 @@ help:
@echo '' @echo ''
@echo 'Here are the targets:' @echo 'Here are the targets:'
@echo '' @echo ''
@echo 'To test : "make check"' @echo 'To test : "make test"'
@echo 'To develop : "make develop"' @echo 'To develop : "make develop"'
@echo 'To install : "make install"' @echo 'To install : "make install"'
@echo 'To format : "make format"' @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 'To clean : "make clean"'
@echo '' @echo ''
@ -20,14 +21,17 @@ develop:
go install github.com/SRI-CSL/gllvm/cmd/... go install github.com/SRI-CSL/gllvm/cmd/...
check: develop test: develop
go test -v ./tests go test -v ./tests
format: format:
gofmt -s -w shared/*.go tests/*.go cmd/*/*.go gofmt -s -w shared/*.go tests/*.go cmd/*/*.go
lint: check:
golint ./shared/ ./tests/ ./cmd/... staticcheck ./...
vet:
go vet ./...
clean: clean:
rm -f data/*hello data/*.bc [td]*/.*.c.o [td]*/*.o [td]*/.*.c.o.bc data/*.notanextensionthatwerecognize rm -f data/*hello data/*.bc [td]*/.*.c.o [td]*/*.o [td]*/.*.c.o.bc data/*.notanextensionthatwerecognize

View File

@ -35,7 +35,6 @@ package shared
import ( import (
"io" "io"
"io/ioutil"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
@ -49,7 +48,7 @@ type bitcodeToObjectLink struct {
objPath string 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) { func Compile(args []string, compiler string) (exitCode int) {
exitCode = 0 exitCode = 0
@ -84,8 +83,8 @@ func Compile(args []string, compiler string) (exitCode int) {
if compiler == "flang" { if compiler == "flang" {
wg.Add(1) wg.Add(1)
go execCompile(compilerExecName, pr, &wg, &ok) go execCompile(compilerExecName, pr, &wg, &ok)
wg.Wait(); wg.Wait()
wg.Add(1); wg.Add(1)
go buildAndAttachBitcode(compilerExecName, pr, &bcObjLinks, &newObjectFiles, &wg) go buildAndAttachBitcode(compilerExecName, pr, &bcObjLinks, &newObjectFiles, &wg)
wg.Wait() wg.Wait()
} else { } else {
@ -191,7 +190,7 @@ func injectPath(extension, bcFile, objFile string) (success bool) {
// Store bitcode path to temp file // Store bitcode path to temp file
var absBcPath, _ = filepath.Abs(bcFile) var absBcPath, _ = filepath.Abs(bcFile)
tmpContent := []byte(absBcPath + "\n") tmpContent := []byte(absBcPath + "\n")
tmpFile, err := ioutil.TempFile("", "gllvm") tmpFile, err := os.CreateTemp("", "gllvm")
if err != nil { if err != nil {
LogError("attachBitcodePathToObject: %v\n", err) LogError("attachBitcodePathToObject: %v\n", err)
return return
@ -313,10 +312,12 @@ func execCompile(compilerExecName string, pr ParserResult, wg *sync.WaitGroup, o
// But for the now, we just remove forbidden arguments // But for the now, we just remove forbidden arguments
var success bool var success bool
var err error var err error
var linking = false
// start afresh // start afresh
arguments := []string{} arguments := []string{}
// we are linking rather than compiling // we are linking rather than compiling
if len(pr.InputFiles) == 0 && len(pr.LinkArgs) > 0 { if len(pr.InputFiles) == 0 && len(pr.LinkArgs) > 0 {
linking = true
if pr.IsLTO { if pr.IsLTO {
arguments = append(arguments, LLVMLtoLDFLAGS...) arguments = append(arguments, LLVMLtoLDFLAGS...)
} }
@ -338,6 +339,11 @@ func execCompile(compilerExecName string, pr ParserResult, wg *sync.WaitGroup, o
} else { } else {
arguments = append(arguments, pr.InputList...) 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) LogDebug("Calling execCmd(%v, %v)", compilerExecName, arguments)
success, err = execCmd(compilerExecName, arguments, "") success, err = execCmd(compilerExecName, arguments, "")
if !success { 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 // GetCompilerExecName returns the full path of the executable
func GetCompilerExecName(compiler string) string { func GetCompilerExecName(compiler string) string {
switch compiler { 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) { func CheckDefer(f func() error) {
if err := f(); err != nil { if err := f(); err != nil {
LogWarning("CheckDefer received error: %v\n", err) LogWarning("CheckDefer received error: %v\n", err)

View File

@ -50,49 +50,49 @@ const (
DarwinSectionName = "__llvm_bc" 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 var LLVMLtoLDFLAGS []string
const ( const (

View File

@ -39,7 +39,6 @@ import (
"debug/macho" "debug/macho"
"flag" "flag"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path" "path"
@ -50,7 +49,7 @@ import (
"strings" "strings"
) )
//ExtractionArgs encapsulate the results of parsing the commandline options // ExtractionArgs encapsulate the results of parsing the commandline options
type ExtractionArgs struct { type ExtractionArgs struct {
Failure bool // indicates failure in parsing the cmd line args Failure bool // indicates failure in parsing the cmd line args
Verbose bool // inform the user of what is going on Verbose bool // inform the user of what is going on
@ -71,7 +70,7 @@ type ExtractionArgs struct {
Extractor func(string) ([]string, bool) 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 { func (ea ExtractionArgs) String() string {
format := format :=
` `
@ -93,7 +92,7 @@ ea.StrictExtract: %v
ea.LlvmLinkerName, ea.ArchiverName, ea.StrictExtract) 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) { func ParseSwitches(args []string) (ea ExtractionArgs) {
var flagSet *flag.FlagSet = flag.NewFlagSet(args[0], flag.ContinueOnError) var flagSet *flag.FlagSet = flag.NewFlagSet(args[0], flag.ContinueOnError)
@ -145,7 +144,7 @@ func ParseSwitches(args []string) (ea ExtractionArgs) {
return 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) { func Extract(args []string) (exitCode int) {
exitCode = 1 exitCode = 1
@ -443,20 +442,20 @@ func extractFiles(ea ExtractionArgs, inputFile string, toc map[string]int) (succ
return 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 // 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. // 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 // 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. // 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 // 3. it then either links all these bitcode files together using llvm-link, or else is creates a bitcode
// archive using llvm-ar // archive using llvm-ar
// //
//iam: 5/1/2018 // iam: 5/1/2018
func handleArchive(ea ExtractionArgs) (success bool) { func handleArchive(ea ExtractionArgs) (success bool) {
// List bitcode files to link // List bitcode files to link
var bcFiles []string var bcFiles []string
@ -467,7 +466,7 @@ func handleArchive(ea ExtractionArgs) (success bool) {
LogInfo("handleArchive: ExtractionArgs = %v\n", ea) LogInfo("handleArchive: ExtractionArgs = %v\n", ea)
// Create tmp dir // Create tmp dir
tmpDirName, err := ioutil.TempDir("", "gllvm") tmpDirName, err := os.MkdirTemp("", "gllvm")
if err != nil { if err != nil {
LogError("The temporary directory in which to extract object files could not be created.") LogError("The temporary directory in which to extract object files could not be created.")
return return
@ -607,7 +606,7 @@ func fetchArgMax(ea ExtractionArgs) (argMax int) {
func linkBitcodeFilesIncrementally(ea ExtractionArgs, filesToLink []string, argMax int, linkArgs []string) (success bool) { func linkBitcodeFilesIncrementally(ea ExtractionArgs, filesToLink []string, argMax int, linkArgs []string) (success bool) {
var tmpFileList []string var tmpFileList []string
// Create tmp dir // Create tmp dir
tmpDirName, err := ioutil.TempDir(".", "glinking") tmpDirName, err := os.MkdirTemp(".", "glinking")
if err != nil { if err != nil {
LogError("The temporary directory in which to put temporary linking files could not be created.") LogError("The temporary directory in which to put temporary linking files could not be created.")
return return
@ -619,7 +618,7 @@ func linkBitcodeFilesIncrementally(ea ExtractionArgs, filesToLink []string, argM
LogInfo("Keeping the temporary folder") LogInfo("Keeping the temporary folder")
} }
tmpFile, err := ioutil.TempFile(tmpDirName, "tmp") tmpFile, err := os.CreateTemp(tmpDirName, "tmp")
if err != nil { if err != nil {
LogError("The temporary linking file could not be created.") LogError("The temporary linking file could not be created.")
return return
@ -643,7 +642,7 @@ func linkBitcodeFilesIncrementally(ea ExtractionArgs, filesToLink []string, argM
if ea.Verbose { if ea.Verbose {
linkArgs = append(linkArgs, "-v") linkArgs = append(linkArgs, "-v")
} }
tmpFile, err = ioutil.TempFile(tmpDirName, "tmp") tmpFile, err = os.CreateTemp(tmpDirName, "tmp")
if err != nil { if err != nil {
LogError("Could not generate a temp file in %s because %v.\n", tmpDirName, err) LogError("Could not generate a temp file in %s because %v.\n", tmpDirName, err)
success = false 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" 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") section2 := "Build-time location of extracted files:\n" + strings.Join(artifactFiles, "\n")
contents := []byte(section1 + section2) 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) LogError("There was an error while writing the manifest file: ", err)
return return
} }
} else { } else {
contents := []byte("\n" + strings.Join(bcFiles, "\n") + "\n") 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) LogError("There was an error while writing the manifest file: ", err)
return return
} }

View File

@ -195,7 +195,7 @@ func MachoFileType(objectFile string) (code BinaryType, err error) {
return 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) { func IsObjectFileForOS(objectFile string, operatingSys string) (ok bool, err error) {
plain := IsPlainFile(objectFile) plain := IsPlainFile(objectFile)
if !plain { if !plain {
@ -231,7 +231,7 @@ const (
fileTypeERROR 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) // often missing on docker images (the klee docker file had this problem)
// this is only used in extraction, not in compilation. // this is only used in extraction, not in compilation.
func getFileType(realPath string) (fileType int, err error) { func getFileType(realPath string) (fileType int, err error) {

View File

@ -46,7 +46,7 @@ const (
debugV debugV
) )
//loggingLevels is the accepted logging levels. // loggingLevels is the accepted logging levels.
var loggingLevels = map[string]int{ var loggingLevels = map[string]int{
"ERROR": errorV, "ERROR": errorV,
"WARNING": warningV, "WARNING": warningV,
@ -61,10 +61,10 @@ var loggingPrefixes = map[int]string{
debugV: "DEBUG:", 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 var loggingLevel = warningV
//loggingFilePointer is where the logging is streamed too. // loggingFilePointer is where the logging is streamed too.
var loggingFilePointer = os.Stderr var loggingFilePointer = os.Stderr
func init() { 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) 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) 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) 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) 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) var LogWrite = makeLogger(-1)
func informUser(format string, a ...interface{}) { func informUser(format string, a ...interface{}) {

View File

@ -44,7 +44,7 @@ import (
"strings" "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 { type ParserResult struct {
InputList []string InputList []string
InputFiles []string InputFiles []string
@ -113,7 +113,7 @@ type argPattern struct {
finfo flagInfo 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 { func (pr *ParserResult) SkipBitcodeGeneration() bool {
reason := "No particular reason" reason := "No particular reason"
retval := false retval := false
@ -155,7 +155,7 @@ func (pr *ParserResult) SkipBitcodeGeneration() bool {
return retval 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 { func Parse(argList []string) ParserResult {
var pr = ParserResult{} var pr = ParserResult{}
pr.InputList = argList pr.InputList = argList

View File

@ -102,13 +102,12 @@ type sanityArgs struct {
// SanityCheck performs the environmental sanity check. // SanityCheck performs the environmental sanity check.
// //
// Performs the following checks in order: // Performs the following checks in order:
// 0. Check the logging // 0. Check the logging
// 1. Check that the OS is supported. // 1. Check that the OS is supported.
// 2. Checks that the compiler settings make sense. // 2. Checks that the compiler settings make sense.
// 3. Checks that the needed LLVM utilities exists. // 3. Checks that the needed LLVM utilities exists.
// 4. Check that the store, if set, exists. // 4. Check that the store, if set, exists.
//
func SanityCheck() { func SanityCheck() {
sa := parseSanitySwitches() sa := parseSanitySwitches()