mirror of
https://github.com/danog/gllvm.git
synced 2024-11-30 06:39:06 +01:00
issue #31 plus continued race detection stuff.
This commit is contained in:
parent
64ececee96
commit
fc48468746
@ -44,6 +44,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
REPLAY_MODE = true
|
||||||
|
)
|
||||||
|
|
||||||
type bitcodeToObjectLink struct {
|
type bitcodeToObjectLink struct {
|
||||||
bcPath string
|
bcPath string
|
||||||
objPath string
|
objPath string
|
||||||
@ -51,6 +55,11 @@ type bitcodeToObjectLink struct {
|
|||||||
|
|
||||||
//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) {
|
||||||
|
|
||||||
|
if REPLAY_MODE {
|
||||||
|
Record(args, compiler)
|
||||||
|
}
|
||||||
|
|
||||||
exitCode = 0
|
exitCode = 0
|
||||||
//in the configureOnly case we have to know the exit code of the compile
|
//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.
|
//because that is how configure figures out what it can and cannot do.
|
||||||
|
@ -61,6 +61,7 @@ type extractionArgs struct {
|
|||||||
InputFile string
|
InputFile string
|
||||||
OutputFile string
|
OutputFile string
|
||||||
LinkerName string
|
LinkerName string
|
||||||
|
LlvmArchiverName string
|
||||||
ArchiverName string
|
ArchiverName string
|
||||||
ArArgs []string
|
ArArgs []string
|
||||||
Extractor func(string) []string
|
Extractor func(string) []string
|
||||||
@ -151,8 +152,9 @@ func resolveTool(defaultPath string, envPath string, usrPath string) (path strin
|
|||||||
|
|
||||||
func parseSwitches() (ea extractionArgs) {
|
func parseSwitches() (ea extractionArgs) {
|
||||||
ea = extractionArgs{
|
ea = extractionArgs{
|
||||||
LinkerName: "llvm-link",
|
LinkerName: "llvm-link",
|
||||||
ArchiverName: "llvm-ar",
|
LlvmArchiverName: "llvm-ar",
|
||||||
|
ArchiverName: "ar",
|
||||||
}
|
}
|
||||||
|
|
||||||
verbosePtr := flag.Bool("v", false, "verbose mode")
|
verbosePtr := flag.Bool("v", false, "verbose mode")
|
||||||
@ -165,9 +167,11 @@ func parseSwitches() (ea extractionArgs) {
|
|||||||
|
|
||||||
outputFilePtr := flag.String("o", "", "the output file")
|
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)")
|
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.LinkArgSize = *linkArgSizePtr
|
||||||
ea.KeepTemp = *keepTempPtr
|
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)
|
ea.LinkerName = resolveTool(ea.LinkerName, LLVMLINKName, *linkerNamePtr)
|
||||||
|
|
||||||
@ -193,7 +201,7 @@ func parseSwitches() (ea extractionArgs) {
|
|||||||
LogInfo("ea.Verbose: %v\n", ea.Verbose)
|
LogInfo("ea.Verbose: %v\n", ea.Verbose)
|
||||||
LogInfo("ea.WriteManifest: %v\n", ea.WriteManifest)
|
LogInfo("ea.WriteManifest: %v\n", ea.WriteManifest)
|
||||||
LogInfo("ea.BuildBitcodeModule: %v\n", ea.BuildBitcodeModule)
|
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.LinkerName: %v\n", ea.LinkerName)
|
||||||
LogInfo("ea.OutputFile: %v\n", ea.OutputFile)
|
LogInfo("ea.OutputFile: %v\n", ea.OutputFile)
|
||||||
|
|
||||||
@ -259,7 +267,7 @@ func handleThinArchive(ea extractionArgs) {
|
|||||||
var objectFiles []string
|
var objectFiles []string
|
||||||
var bcFiles []string
|
var bcFiles []string
|
||||||
|
|
||||||
objectFiles = listArchiveFiles(ea.InputFile)
|
objectFiles = listArchiveFiles(ea, ea.InputFile)
|
||||||
|
|
||||||
LogInfo("handleThinArchive: extractionArgs = %v\nobjectFiles = %v\n", ea, objectFiles)
|
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
|
var arArgs []string
|
||||||
arArgs = append(arArgs, "-t")
|
arArgs = append(arArgs, "-t")
|
||||||
arArgs = append(arArgs, inputFile)
|
arArgs = append(arArgs, inputFile)
|
||||||
@ -322,7 +330,7 @@ func listArchiveFiles(inputFile string) (contents []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractFile(archive string, filename string, instance int) bool {
|
func extractFile(ea extractionArgs, archive string, filename string, instance int) bool {
|
||||||
var arArgs []string
|
var arArgs []string
|
||||||
if runtime.GOOS != osDARWIN {
|
if runtime.GOOS != osDARWIN {
|
||||||
arArgs = append(arArgs, "xN")
|
arArgs = append(arArgs, "xN")
|
||||||
@ -344,10 +352,10 @@ func extractFile(archive string, filename string, instance int) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchTOC(inputFile string) map[string]int {
|
func fetchTOC(ea extractionArgs, inputFile string) map[string]int {
|
||||||
toc := make(map[string]int)
|
toc := make(map[string]int)
|
||||||
|
|
||||||
contents := listArchiveFiles(inputFile)
|
contents := listArchiveFiles(ea, inputFile)
|
||||||
|
|
||||||
for _, item := range contents {
|
for _, item := range contents {
|
||||||
//iam: this is a hack to make get-bc work on libcurl.a
|
//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
|
//1. fetch the Table of Contents
|
||||||
toc := fetchTOC(inputFile)
|
toc := fetchTOC(ea, inputFile)
|
||||||
|
|
||||||
LogDebug("Table of Contents of %v:\n%v\n", inputFile, toc)
|
LogDebug("Table of Contents of %v:\n%v\n", inputFile, toc)
|
||||||
|
|
||||||
for obj, instance := range toc {
|
for obj, instance := range toc {
|
||||||
for i := 1; i <= instance; i++ {
|
for i := 1; i <= instance; i++ {
|
||||||
|
|
||||||
if obj != "" && extractFile(inputFile, obj, i) {
|
if obj != "" && extractFile(ea, inputFile, obj, i) {
|
||||||
|
|
||||||
artifacts := ea.Extractor(obj)
|
artifacts := ea.Extractor(obj)
|
||||||
LogInfo("\t%v\n", artifacts)
|
LogInfo("\t%v\n", artifacts)
|
||||||
@ -469,8 +477,8 @@ func archiveBcFiles(ea extractionArgs, bcFiles []string) {
|
|||||||
var args []string
|
var args []string
|
||||||
args = append(args, "rs", absOutputFile)
|
args = append(args, "rs", absOutputFile)
|
||||||
args = append(args, bcFilesInDir...)
|
args = append(args, bcFilesInDir...)
|
||||||
success, err := execCmd(ea.ArchiverName, args, dir)
|
success, err := execCmd(ea.LlvmArchiverName, args, dir)
|
||||||
LogInfo("ea.ArchiverName = %s, args = %v, dir = %s\n", ea.ArchiverName, args, dir)
|
LogInfo("ea.LlvmArchiverName = %s, args = %v, dir = %s\n", ea.LlvmArchiverName, args, dir)
|
||||||
if !success {
|
if !success {
|
||||||
LogFatal("There was an error creating the bitcode archive: %v.\n", err)
|
LogFatal("There was an error creating the bitcode archive: %v.\n", err)
|
||||||
}
|
}
|
||||||
|
@ -26,11 +26,15 @@ const (
|
|||||||
func Record(args []string, compiler string) {
|
func Record(args []string, compiler string) {
|
||||||
logfile := os.Getenv(recording_env_var)
|
logfile := os.Getenv(recording_env_var)
|
||||||
if len(logfile) > 0 {
|
if len(logfile) > 0 {
|
||||||
fp, err := os.OpenFile(logfile, os.O_WRONLY | os.O_APPEND | os.O_CREATE, os.ModePerm)
|
fp, err := os.OpenFile(logfile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.ModePerm)
|
||||||
if err != nil { panic(err) }
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
defer fp.Close()
|
defer fp.Close()
|
||||||
dir, err := os.Getwd()
|
dir, err := os.Getwd()
|
||||||
if err != nil { panic(err) }
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
fp.WriteString(dir)
|
fp.WriteString(dir)
|
||||||
fp.WriteString("\n")
|
fp.WriteString("\n")
|
||||||
fp.WriteString(compiler)
|
fp.WriteString(compiler)
|
||||||
@ -43,23 +47,21 @@ func Record(args []string, compiler string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type CompilerCall struct {
|
type CompilerCall struct {
|
||||||
Pwd string
|
Pwd string
|
||||||
Name string
|
Name string
|
||||||
Args []string
|
Args []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func readCompilerCall(scanner *bufio.Scanner) (call *CompilerCall) {
|
func readCompilerCall(scanner *bufio.Scanner) (call *CompilerCall) {
|
||||||
if scanner.Scan() {
|
if scanner.Scan() {
|
||||||
//got one line, probably an entire call too ...
|
//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()
|
line := scanner.Text()
|
||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
panic("empty CompilerCall.Pwd")
|
panic("empty CompilerCall.Pwd")
|
||||||
}
|
}
|
||||||
call.Pwd = line
|
callp.Pwd = line
|
||||||
if !scanner.Scan() {
|
if !scanner.Scan() {
|
||||||
panic("non-existant CompilerCall.Name")
|
panic("non-existant CompilerCall.Name")
|
||||||
}
|
}
|
||||||
@ -67,37 +69,42 @@ func readCompilerCall(scanner *bufio.Scanner) (call *CompilerCall) {
|
|||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
panic("empty CompilerCall.Name")
|
panic("empty CompilerCall.Name")
|
||||||
}
|
}
|
||||||
call.Name = line
|
callp.Name = line
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line = scanner.Text()
|
line = scanner.Text()
|
||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
if len(call.Args) == 0 {
|
if len(callp.Args) == 0 {
|
||||||
panic("empty CompilerCall.Args")
|
panic("empty CompilerCall.Args")
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
call.Args = append(call.Args, line)
|
callp.Args = append(callp.Args, line)
|
||||||
}
|
}
|
||||||
call = callp
|
call = callp
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
func Replay(path string) (ok bool) {
|
func Replay(path string) (ok bool) {
|
||||||
fp, err := os.OpenFile(path, os.O_RDONLY, os.ModePerm)
|
fp, err := os.OpenFile(path, os.O_RDONLY, os.ModePerm)
|
||||||
if err != nil { return }
|
if err != nil {
|
||||||
defer fp.Close()
|
return
|
||||||
|
}
|
||||||
|
defer fp.Close()
|
||||||
scanner := bufio.NewScanner(fp)
|
scanner := bufio.NewScanner(fp)
|
||||||
for {
|
for {
|
||||||
callp := readCompilerCall(scanner)
|
callp := readCompilerCall(scanner)
|
||||||
if callp == nil { return }
|
if callp == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
ok = replayCall(callp)
|
ok = replayCall(callp)
|
||||||
if !ok { return }
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ok = true
|
ok = true
|
||||||
return
|
return
|
||||||
@ -108,7 +115,9 @@ func Replay(path string) (ok bool) {
|
|||||||
*/
|
*/
|
||||||
func replayCall(call *CompilerCall) bool {
|
func replayCall(call *CompilerCall) bool {
|
||||||
err := os.Chdir(call.Pwd)
|
err := os.Chdir(call.Pwd)
|
||||||
if err != nil { panic(err) }
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
exitCode := Compile(call.Args, call.Name)
|
exitCode := Compile(call.Args, call.Name)
|
||||||
if exitCode != 0 {
|
if exitCode != 0 {
|
||||||
return false
|
return false
|
||||||
|
21
tests/replay_test.go
Normal file
21
tests/replay_test.go
Normal file
@ -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")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user