diff --git a/shared/compiler.go b/shared/compiler.go index d254c4e..5f358cc 100644 --- a/shared/compiler.go +++ b/shared/compiler.go @@ -44,6 +44,10 @@ import ( "sync" ) +const ( + REPLAY_MODE = true +) + type bitcodeToObjectLink struct { bcPath string objPath string @@ -51,6 +55,11 @@ type bitcodeToObjectLink struct { //Compile wraps a call to the compiler with the given args. func Compile(args []string, compiler string) (exitCode int) { + + if REPLAY_MODE { + Record(args, compiler) + } + exitCode = 0 //in the configureOnly case we have to know the exit code of the compile //because that is how configure figures out what it can and cannot do. diff --git a/shared/extractor.go b/shared/extractor.go index 8f1542c..72407e3 100644 --- a/shared/extractor.go +++ b/shared/extractor.go @@ -61,6 +61,7 @@ type extractionArgs struct { InputFile string OutputFile string LinkerName string + LlvmArchiverName string ArchiverName string ArArgs []string Extractor func(string) []string @@ -151,8 +152,9 @@ func resolveTool(defaultPath string, envPath string, usrPath string) (path strin func parseSwitches() (ea extractionArgs) { ea = extractionArgs{ - LinkerName: "llvm-link", - ArchiverName: "llvm-ar", + LinkerName: "llvm-link", + LlvmArchiverName: "llvm-ar", + ArchiverName: "ar", } verbosePtr := flag.Bool("v", false, "verbose mode") @@ -165,9 +167,11 @@ func parseSwitches() (ea extractionArgs) { outputFilePtr := flag.String("o", "", "the output file") - archiverNamePtr := flag.String("a", "", "the llvm archiver") + llvmArchiverNamePtr := flag.String("a", "", "the llvm archiver (i.e. llvm-ar)") - linkerNamePtr := flag.String("l", "", "the llvm linker") + archiverNamePtr := flag.String("r", "", "the system archiver (i.e. ar)") + + linkerNamePtr := flag.String("l", "", "the llvm linker (i.e. llvm-link)") linkArgSizePtr := flag.Int("n", 0, "maximum llvm-link command line size (in bytes)") @@ -182,7 +186,11 @@ func parseSwitches() (ea extractionArgs) { ea.LinkArgSize = *linkArgSizePtr ea.KeepTemp = *keepTempPtr - ea.ArchiverName = resolveTool(ea.ArchiverName, LLVMARName, *archiverNamePtr) + if len(*archiverNamePtr) > 0 { + ea.ArchiverName = *archiverNamePtr + } + + ea.LlvmArchiverName = resolveTool(ea.LlvmArchiverName, LLVMARName, *llvmArchiverNamePtr) ea.LinkerName = resolveTool(ea.LinkerName, LLVMLINKName, *linkerNamePtr) @@ -193,7 +201,7 @@ func parseSwitches() (ea extractionArgs) { LogInfo("ea.Verbose: %v\n", ea.Verbose) LogInfo("ea.WriteManifest: %v\n", ea.WriteManifest) LogInfo("ea.BuildBitcodeModule: %v\n", ea.BuildBitcodeModule) - LogInfo("ea.ArchiverName: %v\n", ea.ArchiverName) + LogInfo("ea.LlvmArchiverName: %v\n", ea.LlvmArchiverName) LogInfo("ea.LinkerName: %v\n", ea.LinkerName) LogInfo("ea.OutputFile: %v\n", ea.OutputFile) @@ -259,7 +267,7 @@ func handleThinArchive(ea extractionArgs) { var objectFiles []string var bcFiles []string - objectFiles = listArchiveFiles(ea.InputFile) + objectFiles = listArchiveFiles(ea, ea.InputFile) LogInfo("handleThinArchive: extractionArgs = %v\nobjectFiles = %v\n", ea, objectFiles) @@ -309,7 +317,7 @@ func handleThinArchive(ea extractionArgs) { } -func listArchiveFiles(inputFile string) (contents []string) { +func listArchiveFiles(ea extractionArgs, inputFile string) (contents []string) { var arArgs []string arArgs = append(arArgs, "-t") arArgs = append(arArgs, inputFile) @@ -322,7 +330,7 @@ func listArchiveFiles(inputFile string) (contents []string) { return } -func extractFile(archive string, filename string, instance int) bool { +func extractFile(ea extractionArgs, archive string, filename string, instance int) bool { var arArgs []string if runtime.GOOS != osDARWIN { arArgs = append(arArgs, "xN") @@ -344,10 +352,10 @@ func extractFile(archive string, filename string, instance int) bool { return true } -func fetchTOC(inputFile string) map[string]int { +func fetchTOC(ea extractionArgs, inputFile string) map[string]int { toc := make(map[string]int) - contents := listArchiveFiles(inputFile) + contents := listArchiveFiles(ea, inputFile) for _, item := range contents { //iam: this is a hack to make get-bc work on libcurl.a @@ -399,14 +407,14 @@ func handleArchive(ea extractionArgs) { } //1. fetch the Table of Contents - toc := fetchTOC(inputFile) + toc := fetchTOC(ea, inputFile) LogDebug("Table of Contents of %v:\n%v\n", inputFile, toc) for obj, instance := range toc { for i := 1; i <= instance; i++ { - if obj != "" && extractFile(inputFile, obj, i) { + if obj != "" && extractFile(ea, inputFile, obj, i) { artifacts := ea.Extractor(obj) LogInfo("\t%v\n", artifacts) @@ -469,8 +477,8 @@ func archiveBcFiles(ea extractionArgs, bcFiles []string) { var args []string args = append(args, "rs", absOutputFile) args = append(args, bcFilesInDir...) - success, err := execCmd(ea.ArchiverName, args, dir) - LogInfo("ea.ArchiverName = %s, args = %v, dir = %s\n", ea.ArchiverName, args, dir) + success, err := execCmd(ea.LlvmArchiverName, args, dir) + LogInfo("ea.LlvmArchiverName = %s, args = %v, dir = %s\n", ea.LlvmArchiverName, args, dir) if !success { LogFatal("There was an error creating the bitcode archive: %v.\n", err) } diff --git a/shared/replay.go b/shared/replay.go index 0c835d1..6ef2783 100644 --- a/shared/replay.go +++ b/shared/replay.go @@ -26,11 +26,15 @@ const ( func Record(args []string, compiler string) { logfile := os.Getenv(recording_env_var) if len(logfile) > 0 { - fp, err := os.OpenFile(logfile, os.O_WRONLY | os.O_APPEND | os.O_CREATE, os.ModePerm) - if err != nil { panic(err) } + fp, err := os.OpenFile(logfile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.ModePerm) + if err != nil { + panic(err) + } defer fp.Close() dir, err := os.Getwd() - if err != nil { panic(err) } + if err != nil { + panic(err) + } fp.WriteString(dir) fp.WriteString("\n") fp.WriteString(compiler) @@ -43,23 +47,21 @@ func Record(args []string, compiler string) { } } - type CompilerCall struct { - Pwd string + Pwd string Name string Args []string } - func readCompilerCall(scanner *bufio.Scanner) (call *CompilerCall) { if scanner.Scan() { //got one line, probably an entire call too ... - callp := new(CompilerCall) //pass in a local version later, save on mallocing. + callp := new(CompilerCall) //pass in a local version later, save on mallocing. line := scanner.Text() if len(line) == 0 { panic("empty CompilerCall.Pwd") } - call.Pwd = line + callp.Pwd = line if !scanner.Scan() { panic("non-existant CompilerCall.Name") } @@ -67,37 +69,42 @@ func readCompilerCall(scanner *bufio.Scanner) (call *CompilerCall) { if len(line) == 0 { panic("empty CompilerCall.Name") } - call.Name = line + callp.Name = line for scanner.Scan() { line = scanner.Text() if len(line) == 0 { - if len(call.Args) == 0 { + if len(callp.Args) == 0 { panic("empty CompilerCall.Args") } break } - call.Args = append(call.Args, line) + callp.Args = append(callp.Args, line) } call = callp } return } - /* * */ func Replay(path string) (ok bool) { fp, err := os.OpenFile(path, os.O_RDONLY, os.ModePerm) - if err != nil { return } - defer fp.Close() + if err != nil { + return + } + defer fp.Close() scanner := bufio.NewScanner(fp) for { callp := readCompilerCall(scanner) - if callp == nil { return } + if callp == nil { + return + } ok = replayCall(callp) - if !ok { return } + if !ok { + return + } } ok = true return @@ -108,7 +115,9 @@ func Replay(path string) (ok bool) { */ func replayCall(call *CompilerCall) bool { err := os.Chdir(call.Pwd) - if err != nil { panic(err) } + if err != nil { + panic(err) + } exitCode := Compile(call.Args, call.Name) if exitCode != 0 { return false diff --git a/tests/replay_test.go b/tests/replay_test.go new file mode 100644 index 0000000..f1b14f7 --- /dev/null +++ b/tests/replay_test.go @@ -0,0 +1,21 @@ +package test + +import ( + "github.com/SRI-CSL/gllvm/shared" + "testing" + "fmt" +) + + +func Test_replay_thttpd(t *testing.T) { + arg := "../data/thttpd_reply.log" + + + ok := shared.Replay(arg) + + if !ok { + t.Errorf("Replay of %v returned %v\n", arg, ok) + } else { + fmt.Println("Replay OK") + } +}