conflict fix.

This commit is contained in:
Ian A. Mason 2018-05-04 06:48:47 -07:00
commit 8a6e56d02d
22 changed files with 1762 additions and 90 deletions

View File

@ -4,7 +4,7 @@
[![Go Report Card](https://goreportcard.com/badge/github.com/SRI-CSL/gllvm)](https://goreportcard.com/report/github.com/SRI-CSL/gllvm)
**TL; DR:** A drop-in replacement for [wllvm](https://github.com/SRI-CSL/whole-program-llvm), that builds the
bitcode in parallel, and is faster.
bitcode in parallel, and is faster. A comparison between the two tools can be gleaned from building the [Linux kernel.](https://github.com/SRI-CSL/gllvm/tree/master/examples/linux-kernel)
## Quick Start Comparison Table

View File

@ -39,14 +39,14 @@ import (
)
func main() {
shared.LogInfo("Entering %v\n", os.Args)
shared.LogInfo("Entering CC %v\n", os.Args[1:])
// Parse command line
args := os.Args
args = args[1:]
exitCode := shared.Compile(args, "clang")
shared.LogInfo("Calling %v returned %v\n", os.Args, exitCode)
shared.LogDebug("Calling %v returned %v\n", os.Args, exitCode)
//important to pretend to look like the actual wrapped command
os.Exit(exitCode)

8
examples/README.md Normal file
View File

@ -0,0 +1,8 @@
# Examples of using GLLVM
A simple set of instructions for building apache in a vagrant Ubuntu 14.04 can be found
[here,](tutorial.md) and for Ubuntu 16.04 [here.](tutorial-ubuntu-16.04.md)
The big example here though is the [linux kernel.](linux-kernel)

View File

@ -0,0 +1,118 @@
# Building a recent Linux Kernel.
In this directory we include all the necessary files needed to
build the kernel in a Ubuntu 16.04 vagrant box. We will guide the reader through
the relatively simple task. We assume familiarity with [Vagrant.](https://www.vagrantup.com/)
## Vagrantfile
```ruby
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.provision :shell, path: "bootstrap.sh"
config.vm.provider "virtualbox" do |vb|
vb.memory = "4096"
vb.customize ["modifyvm", :id, "--ioapic", "on"]
vb.customize ["modifyvm", :id, "--memory", "4096"]
vb.customize ["modifyvm", :id, "--cpus", "4"]
end
end
```
## Bootstrapping
```bash
#!/usr/bin/env bash
sudo apt-get update
sudo apt-get install -y emacs24 dbus-x11
sudo apt-get install -y git
sudo apt-get install -y llvm-5.0 libclang-5.0-dev clang-5.0
sudo apt-get install -y python-pip golang-go
sudo apt-get install -y flex bison bc libncurses5-dev
sudo apt-get install -y libelf-dev libssl-dev
echo ". /vagrant/bash_profile" >> /home/vagrant/.bashrc
```
## Shell Settings
```bash
#### llvm
export LLVM_HOME=/usr/lib/llvm-5.0
export GOPATH=/vagrant/go
######## gllvm/wllvm configuration #############
export LLVM_COMPILER=clang
export WLLVM_OUTPUT_LEVEL=WARNING
export WLLVM_OUTPUT_FILE=/vagrant/wrapper.log
export PATH=${GOPATH}/bin:${LLVM_HOME}/bin:${PATH}
```
## Configuration stuff.
The file `tinyconfig64` is generated ...
## The Build with gllvm
The build process is carried out by running the `build_linux_gllvm.sh`
script.
```bash
#!/usr/bin/env bash
mkdir -p ${GOPATH}
go get github.com/SRI-CSL/gllvm/cmd/...
mkdir ${HOME}/linux_kernel
cd ${HOME}/linux_kernel
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
cd linux-stable
git checkout tags/v4.14.34
cp /vagrant/tinyconfig64 .config
make CC=gclang HOSTCC=gclang
get-bc -m -b built-in.o
get-bc -m vmlinux
```
## The Build with wllvm
The build process is carried out by running the `build_linux_wllvm.sh`
script.
```bash
#!/usr/bin/env bash
sudo pip install wllvm
mkdir ${HOME}/linux_kernel
cd ${HOME}/linux_kernel
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
cd linux-stable
git checkout tags/v4.14.34
cp /vagrant/tinyconfig64 .config
make CC=wllvm HOSTCC=wllvm
extract-bc -m -b built-in.o
extract-bc -m vmlinux
```
## Extracting the bitcode

20
examples/linux-kernel/Vagrantfile vendored Normal file
View File

@ -0,0 +1,20 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.provision :shell, path: "bootstrap.sh"
config.vm.provider "virtualbox" do |vb|
vb.memory = "4096"
vb.customize ["modifyvm", :id, "--ioapic", "on"]
vb.customize ["modifyvm", :id, "--memory", "4096"]
vb.customize ["modifyvm", :id, "--cpus", "4"]
end
end

View File

@ -0,0 +1,10 @@
#### llvm
export LLVM_HOME=/usr/lib/llvm-5.0
export GOPATH=/vagrant/go
######## gllvm/wllvm configuration #############
export LLVM_COMPILER=clang
export WLLVM_OUTPUT_LEVEL=WARNING
export WLLVM_OUTPUT_FILE=/vagrant/wrapper.log
export PATH=${GOPATH}/bin:${LLVM_HOME}/bin:${PATH}

View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
sudo apt-get update
sudo apt-get install -y emacs24 dbus-x11
sudo apt-get install -y git
sudo apt-get install -y llvm-5.0 libclang-5.0-dev clang-5.0
sudo apt-get install -y python-pip golang-go
sudo apt-get install -y flex bison bc libncurses5-dev
sudo apt-get install -y libelf-dev libssl-dev
echo ". /vagrant/bash_profile" >> /home/vagrant/.bashrc

View File

@ -0,0 +1,17 @@
#!/usr/bin/env bash
mkdir -p ${GOPATH}
go get github.com/SRI-CSL/gllvm/cmd/...
mkdir ${HOME}/linux_kernel
cd ${HOME}/linux_kernel
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
cd linux-stable
git checkout tags/v4.14.34
cp /vagrant/tinyconfig64 .config
make CC=gclang HOSTCC=gclang
get-bc -m -b built-in.o
get-bc -m vmlinux

View File

@ -0,0 +1,17 @@
#!/usr/bin/env bash
sudo pip install wllvm
mkdir ${HOME}/linux_kernel
cd ${HOME}/linux_kernel
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
cd linux-stable
git checkout tags/v4.14.34
cp /vagrant/tinyconfig64 .config
make CC=wllvm HOSTCC=wllvm
extract-bc -m -b built-in.o
extract-bc -m vmlinux

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
# Compiling Apache on Ubuntu
On a clean 16.04 server machine I will build apache. Desktop instructions should be no different.
```
>more /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04 LTS"
```
## Step 1.
Install `gllvm`.
```
>export GOPATH=/vagrant/go
>mkdir -p ${GOPATH}
>go get github.com/SRI-CSL/gllvm/cmd/...
>export PATH=${GOPATH}/bin:${PATH}
```
## Step 2.
I am only going to build apache, not apr, so I first install the prerequisites.
```
>sudo apt-get install llvm libclang-dev clang libapr1-dev libaprutil1-dev libpcre3-dev make
```
At this point, you could check your clang version with `which clang` and `ls -l /usr/bin/clang`.
It should be at least clang-3.8.
## Step 3.
Configure the gllvm tool to be relatively quiet:
```
>export WLLVM_OUTPUT_LEVEL=WARNING
>export WLLVM_OUTPUT_FILE=/vagrant/apache-build.log
```
## Step 4.
Fetch apache, untar, configure, then build:
```
>wget https://archive.apache.org/dist/httpd/httpd-2.4.33.tar.gz
>tar xfz httpd-2.4.33.tar.gz
>cd httpd-2.4.33
>CC=gllvm ./configure
>make
```
## Step 5.
Extract the bitcode.
```
>get-bc httpd
>ls -la httpd.bc
-rw-r--r-- 1 vagrant vagrant 1119584 Aug 4 20:02 httpd.bc
```
## Step 6.
Turn the bitcode into a second executable binary. (optional -- just for fun and sanity checking)
```
llc -filetype=obj httpd.bc
gcc httpd.o -lpthread -lapr-1 -laprutil-1 -lpcre -o httpd.new
```

82
examples/tutorial.md Normal file
View File

@ -0,0 +1,82 @@
# Compiling Apache on Ubuntu
On a clean 14.04 machine I will build apache.
```
>pwd
/vagrant
>more /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.2 LTS"
```
## Step 1.
Install `gllvm`.
```
>export GOPATH=/vagrant/go
>mkdir -p ${GOPATH}
>go get github.com/SRI-CSL/gllvm/cmd/...
>export PATH=${GOPATH}/bin:${PATH}
```
## Step 2.
I am only going to build apache, not apr, so I first install the prerequisites.
```
>sudo apt-get install llvm libclang-dev clang libapr1-dev libaprutil1-dev
``` Note `gclang` is agnostic with respect to llvm versions
so feel free to install a more recent version if you
wish. However, if you are going to use dragonegg the llvm version is
tightly coupled to the gcc and plugin versions you are using.
## Step 3.
Configure the gllvm tool to be relatively quiet:
```
>export WLLVM_OUTPUT_LEVEL=WARNING
>export WLLVM_OUTPUT_FILE=/vagrant/apache-build.log
```
## Step 4.
Fetch apache, untar, configure, then build:
```
>wget https://archive.apache.org/dist/httpd/httpd-2.4.33.tar.gz
>tar xfz httpd-2.4.33.tar.gz
>cd httpd-2.4.33
>CC=gclang ./configure
>make
```
## Step 5.
Extract the bitcode.
```
>get-bc httpd
```

View File

@ -16,3 +16,5 @@ gofmt -s -w shared/*.go cmd/*/*.go
For linting:
https://github.com/alecthomas/gometalinter
gometalinter.v2 ./...

View File

@ -241,7 +241,7 @@ func buildBitcodeFile(compilerExecName string, pr parserResult, srcFile string,
// Tries to build object file
func execCompile(compilerExecName string, pr parserResult, wg *sync.WaitGroup, ok *bool) {
defer (*wg).Done()
success, err := execCmd(compilerExecName, pr.InputList, "")
success, _ := 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

View File

@ -33,8 +33,18 @@
package shared
const gllvmVersion = "1.0.1"
const gllvmReleaseDate = "April 118 2018"
// Remember to tag the repo, and publish a release on GitHub.
//
// version history:
//
// 1.0.0
// 1.0.1 various bug fixes
// 1.0.2 April 28 2018 linux kernel work, sorting bitcode files, etc.
// May 2 2018 handleArchives rewritten to handle multiple occurrences of files with the same name.
// corresponds with wllvm 1.1.6
//
const gllvmVersion = "1.0.2"
const gllvmReleaseDate = "May 2 2018"
const osDARWIN = "darwin"
const osLINUX = "linux"

View File

@ -103,3 +103,13 @@ func init() {
LLVMLoggingFile = os.Getenv(envfile)
}
func printEnvironment() {
vars := []string{envpath, envcc, envcxx, envar, envlnk, envcfg, envbc, envlvl, envfile}
LogWrite("\nLiving in this environment:\n\n")
for _, v := range vars {
LogWrite("%v = %v\n", v, os.Getenv(v))
}
}

View File

@ -42,6 +42,8 @@ import (
"path"
"path/filepath"
"runtime"
"sort"
"strconv"
"strings"
)
@ -56,6 +58,7 @@ type extractionArgs struct {
Extractor func(string) []string
Verbose bool
WriteManifest bool
SortBitcodeFiles bool
BuildBitcodeArchive bool
}
@ -86,7 +89,7 @@ func Extract(args []string) {
// Create output filename if not given
if ea.OutputFile == "" {
if ea.InputType == fileTypeARCHIVE {
if ea.InputType == fileTypeARCHIVE || ea.InputType == fileTypeTHINARCHIVE {
var ext string
if ea.BuildBitcodeArchive {
ext = ".a.bc"
@ -109,6 +112,8 @@ func Extract(args []string) {
handleExecutable(ea)
case fileTypeARCHIVE:
handleArchive(ea)
case fileTypeTHINARCHIVE:
handleThinArchive(ea)
default:
LogFatal("Incorrect input file type %v.", ea.InputType)
}
@ -125,6 +130,8 @@ func parseSwitches() (ea extractionArgs) {
writeManifestPtr := flag.Bool("m", false, "write the manifest")
sortBitcodeFilesPtr := flag.Bool("s", false, "sort the bitcode files")
buildBitcodeArchive := flag.Bool("b", false, "build a bitcode module(FIXME? should this be archive)")
outputFilePtr := flag.String("o", "", "the output file")
@ -137,6 +144,7 @@ func parseSwitches() (ea extractionArgs) {
ea.Verbose = *verbosePtr
ea.WriteManifest = *writeManifestPtr
ea.SortBitcodeFiles = *sortBitcodeFilesPtr
ea.BuildBitcodeArchive = *buildBitcodeArchive
if *archiverNamePtr != "" {
@ -201,20 +209,141 @@ func handleExecutable(ea extractionArgs) {
for i, artPath := range artifactPaths {
filesToLink[i] = resolveBitcodePath(artPath)
}
extractTimeLinkFiles(ea, filesToLink)
// Sort the bitcode files
if ea.SortBitcodeFiles {
LogWarning("Sorting bitcode files.")
sort.Strings(filesToLink)
sort.Strings(artifactPaths)
}
// Write manifest
if ea.WriteManifest {
writeManifest(ea, filesToLink, artifactPaths)
}
extractTimeLinkFiles(ea, filesToLink)
}
func handleThinArchive(ea extractionArgs) {
// List bitcode files to link
var artifactFiles []string
var objectFiles []string
var bcFiles []string
objectFiles = listArchiveFiles(ea.InputFile)
LogInfo("handleThinArchive: extractionArgs = %v\nobjectFiles = %v\n", ea, objectFiles)
for index, obj := range objectFiles {
LogInfo("obj = '%v'\n", obj)
if len(obj) > 0 {
artifacts := ea.Extractor(obj)
LogInfo("\t%v\n", artifacts)
artifactFiles = append(artifactFiles, artifacts...)
for _, bc := range artifacts {
bcPath := resolveBitcodePath(bc)
if bcPath != "" {
bcFiles = append(bcFiles, bcPath)
}
}
} else {
LogDebug("\tskipping empty entry at index %v\n", index)
}
}
LogInfo("bcFiles: %v\n", bcFiles)
LogInfo("len(bcFiles) = %v\n", len(bcFiles))
if len(bcFiles) > 0 {
// Sort the bitcode files
if ea.SortBitcodeFiles {
LogWarning("Sorting bitcode files.")
sort.Strings(bcFiles)
sort.Strings(artifactFiles)
}
// Build archive
if ea.BuildBitcodeArchive {
extractTimeLinkFiles(ea, bcFiles)
} else {
archiveBcFiles(ea, bcFiles)
}
// Write manifest
if ea.WriteManifest {
writeManifest(ea, bcFiles, artifactFiles)
}
} else {
LogError("No bitcode files found\n")
}
}
func listArchiveFiles(inputFile string) (contents []string) {
var arArgs []string
arArgs = append(arArgs, "-t")
arArgs = append(arArgs, inputFile)
output, err := runCmd("ar", arArgs)
if err != nil {
LogWarning("ar command: ar %v", arArgs)
LogFatal("Failed to extract contents from archive %s because: %v.\n", inputFile, err)
}
contents = strings.Split(output, "\n")
return
}
func extractFile(archive string, filename string, instance int) bool {
var arArgs []string
arArgs = append(arArgs, "xN")
arArgs = append(arArgs, strconv.Itoa(instance))
arArgs = append(arArgs, archive)
arArgs = append(arArgs, filename)
_, err := runCmd("ar", arArgs)
if err != nil {
LogWarning("Failed to extract instance %v of %v from archive %s because: %v.\n", instance, filename, archive, err)
return false
}
return true
}
func fetchTOC(inputFile string) map[string]int {
toc := make(map[string]int)
contents := listArchiveFiles(inputFile)
for _, item := range contents {
if item != "" {
toc[item]++
}
}
return toc
}
//handleArchive processes a archive, and creates either a bitcode archive, or a module, depending on the flags used.
//
// 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.
//
// 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
//
//iam: 5/1/2018
func handleArchive(ea extractionArgs) {
// List bitcode files to link
var bcFiles []string
var artifactFiles []string
LogInfo("handleArchive: extractionArgs = %v\n", ea)
inputFile, _ := filepath.Abs(ea.InputFile)
LogWarning("handleArchive: extractionArgs = %v\n", ea)
// Create tmp dir
tmpDirName, err := ioutil.TempDir("", "gllvm")
@ -223,45 +352,55 @@ func handleArchive(ea extractionArgs) {
}
defer CheckDefer(func() error { return os.RemoveAll(tmpDirName) })
// Extract objects to tmpDir
arArgs := ea.ArArgs
inputAbsPath, _ := filepath.Abs(ea.InputFile)
arArgs = append(arArgs, inputAbsPath)
LogInfo("handleArchive: executing ar %v %v\n", arArgs, tmpDirName)
success, err := execCmd("ar", arArgs, tmpDirName)
if !success {
LogFatal("Failed to extract object files from %s to %s because: %v.\n", ea.InputFile, tmpDirName, err)
homeDir, err := os.Getwd()
if err != nil {
LogFatal("Could not ascertain our whereabouts: %v", err)
}
// Define object file handling closure
var walkHandlingFunc = func(path string, info os.FileInfo, err error) error {
if err == nil && !info.IsDir() {
fileType := getFileType(path)
if fileType == ea.ObjectTypeInArchive {
artifactPaths := ea.Extractor(path)
for _, artPath := range artifactPaths {
bcPath := resolveBitcodePath(artPath)
err = os.Chdir(tmpDirName)
if err != nil {
LogFatal("Could not cd to %v because: %v", tmpDirName, err)
}
//1. fetch the Table of Contents
toc := fetchTOC(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) {
artifacts := ea.Extractor(obj)
LogInfo("\t%v\n", artifacts)
artifactFiles = append(artifactFiles, artifacts...)
for _, bc := range artifacts {
bcPath := resolveBitcodePath(bc)
if bcPath != "" {
bcFiles = append(bcFiles, bcPath)
}
}
artifactFiles = append(artifactFiles, artifactPaths...)
}
}
return nil
}
// Handle object files
err = filepath.Walk(tmpDirName, walkHandlingFunc)
err = os.Chdir(homeDir)
if err != nil {
LogFatal("handleArchive: walking %v failed with %v\n", tmpDirName, err)
LogFatal("Could not cd to %v because: %v", homeDir, err)
}
LogDebug("handleArchive: walked %v\nartifactFiles:\n%v\nbcFiles:\n%v\n", tmpDirName, artifactFiles, bcFiles)
if len(bcFiles) > 0 {
// Sort the bitcode files
if ea.SortBitcodeFiles {
LogWarning("Sorting bitcode files.")
sort.Strings(bcFiles)
sort.Strings(artifactFiles)
}
// Build archive
if ea.BuildBitcodeArchive {
extractTimeLinkFiles(ea, bcFiles)
@ -300,7 +439,7 @@ func archiveBcFiles(ea extractionArgs, bcFiles []string) {
LogFatal("There was an error creating the bitcode archive: %v.\n", err)
}
}
LogInfo("Built bitcode archive: %s.", ea.OutputFile)
LogWarning("Built bitcode archive: %s.", ea.OutputFile)
}
func extractTimeLinkFiles(ea extractionArgs, filesToLink []string) {
@ -314,7 +453,7 @@ func extractTimeLinkFiles(ea extractionArgs, filesToLink []string) {
if !success {
LogFatal("There was an error linking input files into %s because %v.\n", ea.OutputFile, err)
}
LogInfo("Bitcode file extracted to: %s.", ea.OutputFile)
LogWarning("Bitcode file extracted to: %s.", ea.OutputFile)
}
func extractSectionDarwin(inputFile string) (contents []string) {
@ -375,12 +514,20 @@ func resolveBitcodePath(bcPath string) string {
}
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)
manifestFilename := ea.OutputFile + ".llvm.manifest"
if err := ioutil.WriteFile(manifestFilename, contents, 0644); err != nil {
LogFatal("There was an error while writing the manifest file: ", err)
//only go into the gory details if we have a store around.
if LLVMBitcodeStorePath != "" {
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 {
LogFatal("There was an error while writing the manifest file: ", err)
}
} else {
contents := []byte("\n" + strings.Join(bcFiles, "\n") + "\n")
if err := ioutil.WriteFile(manifestFilename, contents, 0644); err != nil {
LogFatal("There was an error while writing the manifest file: ", err)
}
}
LogInfo("Manifest file written to %s.", manifestFilename)
LogWarning("Manifest file written to %s.", manifestFilename)
}

View File

@ -48,6 +48,7 @@ const (
fileTypeMACHOBJECT
fileTypeMACHSHARED
fileTypeARCHIVE
fileTypeTHINARCHIVE
)
func getFileType(realPath string) (fileType int) {
@ -58,21 +59,36 @@ func getFileType(realPath string) (fileType int) {
LogFatal("There was an error getting the type of %s. Make sure that the 'file' command is installed.", realPath)
}
// Test the output
if fo := string(out); strings.Contains(fo, "ELF") && strings.Contains(fo, "executable") {
fileType = fileTypeELFEXECUTABLE
} else if strings.Contains(fo, "Mach-O") && strings.Contains(fo, "executable") {
fileType = fileTypeMACHEXECUTABLE
} else if strings.Contains(fo, "ELF") && strings.Contains(fo, "shared") {
fileType = fileTypeELFSHARED
} else if strings.Contains(fo, "Mach-O") && strings.Contains(fo, "dynamically linked shared") {
fileType = fileTypeMACHSHARED
fo := string(out)
if strings.Contains(fo, "ELF") {
if strings.Contains(fo, "executable") {
fileType = fileTypeELFEXECUTABLE
} else if strings.Contains(fo, "shared") {
fileType = fileTypeELFSHARED
} else if strings.Contains(fo, "relocatable") {
fileType = fileTypeELFOBJECT
} else {
fileType = fileTypeUNDEFINED
}
} else if strings.Contains(fo, "Mach-O") {
if strings.Contains(fo, "executable") {
fileType = fileTypeMACHEXECUTABLE
} else if strings.Contains(fo, "dynamically linked shared") {
fileType = fileTypeMACHSHARED
} else if strings.Contains(fo, "object") {
fileType = fileTypeMACHOBJECT
} else {
fileType = fileTypeUNDEFINED
}
} else if strings.Contains(fo, "current ar archive") {
fileType = fileTypeARCHIVE
} else if strings.Contains(fo, "ELF") && strings.Contains(fo, "relocatable") {
fileType = fileTypeELFOBJECT
} else if strings.Contains(fo, "Mach-O") && strings.Contains(fo, "object") {
fileType = fileTypeMACHOBJECT
} else if strings.Contains(fo, "thin archive") {
fileType = fileTypeTHINARCHIVE
} else {
fileType = fileTypeUNDEFINED
}

View File

@ -55,14 +55,14 @@ var loggingLevels = map[string]int{
}
var loggingPrefixes = map[int]string{
errorV: "Error: ",
warningV: "Warning: ",
infoV: "Info: ",
debugV: "Debug: ",
errorV: "ERROR:",
warningV: "WARNING:",
infoV: "INFO:",
debugV: "DEBUG:",
}
//loggingLevel is the user configured level of logging: ERROR, WARNING, INFO, DEBUG
var loggingLevel = errorV
var loggingLevel = warningV
//loggingFilePointer is where the logging is streamed too.
var loggingFilePointer = os.Stderr

View File

@ -88,6 +88,9 @@ func parse(argList []string) parserResult {
pr.InputList = argList
var argsExactMatches = map[string]flagInfo{
"/dev/null": {0, pr.inputFileCallback}, //iam: linux kernel
"-": {0, pr.printOnlyCallback},
"-o": {1, pr.outputFileCallback},
"-c": {0, pr.compileOnlyCallback},
@ -118,41 +121,50 @@ func parse(argList []string) parserResult {
"-nostdlibinc": {0, pr.compileUnaryCallback},
"-mno-omit-leaf-frame-pointer": {0, pr.compileUnaryCallback},
"-maes": {0, pr.compileUnaryCallback},
"-mno-aes": {0, pr.compileUnaryCallback},
"-mavx": {0, pr.compileUnaryCallback},
"-mno-avx": {0, pr.compileUnaryCallback},
"-mavx2": {0, pr.compileUnaryCallback},
"-mno-avx2": {0, pr.compileUnaryCallback},
"-mcmodel=kernel": {0, pr.compileUnaryCallback},
"-mno-red-zone": {0, pr.compileUnaryCallback},
"-mmmx": {0, pr.compileUnaryCallback},
"-mno-mmx": {0, pr.compileUnaryCallback},
"-msse": {0, pr.compileUnaryCallback},
"-mno-sse": {0, pr.compileUnaryCallback},
"-msse2": {0, pr.compileUnaryCallback},
"-mno-sse2": {0, pr.compileUnaryCallback},
"-msse3": {0, pr.compileUnaryCallback},
"-mno-sse3": {0, pr.compileUnaryCallback},
"-mssse3": {0, pr.compileUnaryCallback},
"-mno-ssse3": {0, pr.compileUnaryCallback},
"-msse4": {0, pr.compileUnaryCallback},
"-mno-sse4": {0, pr.compileUnaryCallback},
"-msse4.1": {0, pr.compileUnaryCallback},
"-mno-sse4.1": {0, pr.compileUnaryCallback},
"-msse4.2": {0, pr.compileUnaryCallback},
"-mno-sse4.2": {0, pr.compileUnaryCallback},
"-msoft-float": {0, pr.compileUnaryCallback},
"-m3dnow": {0, pr.compileUnaryCallback},
"-mno-3dnow": {0, pr.compileUnaryCallback},
"-m32": {0, pr.compileUnaryCallback},
"-m64": {0, pr.compileUnaryCallback},
"-mstackrealign": {0, pr.compileUnaryCallback},
"-maes": {0, pr.compileUnaryCallback},
"-mno-aes": {0, pr.compileUnaryCallback},
"-mavx": {0, pr.compileUnaryCallback},
"-mno-avx": {0, pr.compileUnaryCallback},
"-mavx2": {0, pr.compileUnaryCallback},
"-mno-avx2": {0, pr.compileUnaryCallback},
"-mno-red-zone": {0, pr.compileUnaryCallback},
"-mmmx": {0, pr.compileUnaryCallback},
"-mno-mmx": {0, pr.compileUnaryCallback},
"-mno-global-merge": {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
"-mno-80387": {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
"-msse": {0, pr.compileUnaryCallback},
"-mno-sse": {0, pr.compileUnaryCallback},
"-msse2": {0, pr.compileUnaryCallback},
"-mno-sse2": {0, pr.compileUnaryCallback},
"-msse3": {0, pr.compileUnaryCallback},
"-mno-sse3": {0, pr.compileUnaryCallback},
"-mssse3": {0, pr.compileUnaryCallback},
"-mno-ssse3": {0, pr.compileUnaryCallback},
"-msse4": {0, pr.compileUnaryCallback},
"-mno-sse4": {0, pr.compileUnaryCallback},
"-msse4.1": {0, pr.compileUnaryCallback},
"-mno-sse4.1": {0, pr.compileUnaryCallback},
"-msse4.2": {0, pr.compileUnaryCallback},
"-mno-sse4.2": {0, pr.compileUnaryCallback},
"-msoft-float": {0, pr.compileUnaryCallback},
"-m3dnow": {0, pr.compileUnaryCallback},
"-mno-3dnow": {0, pr.compileUnaryCallback},
"-m16": {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
"-m32": {0, pr.compileUnaryCallback},
"-m64": {0, pr.compileUnaryCallback},
"-mstackrealign": {0, pr.compileUnaryCallback},
"-mretpoline-external-thunk": {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
"-mno-fp-ret-in-387": {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
"-mskip-rax-setup": {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
"-mindirect-branch-register": {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
"-A": {1, pr.compileBinaryCallback},
"-D": {1, pr.compileBinaryCallback},
"-U": {1, pr.compileBinaryCallback},
"-P": {1, pr.compileUnaryCallback}, //iam: linux kernel stuff (linker script stuff)
"-C": {1, pr.compileUnaryCallback}, //iam: linux kernel stuff (linker script stuff)
"-M": {0, pr.dependencyOnlyCallback},
"-MM": {0, pr.dependencyOnlyCallback},
"-MF": {1, pr.dependencyBinaryCallback},
@ -198,6 +210,7 @@ func parse(argList []string) parserResult {
"-Os": {0, pr.compileUnaryCallback},
"-Ofast": {0, pr.compileUnaryCallback},
"-Og": {0, pr.compileUnaryCallback},
"-Oz": {0, pr.compileUnaryCallback}, //iam: linux kernel
"-Xclang": {1, pr.compileBinaryCallback},
"-Xpreprocessor": {1, pr.defaultBinaryCallback},
@ -254,6 +267,14 @@ func parse(argList []string) parserResult {
`^--sysroot=.+$`: {0, pr.compileUnaryCallback},
`^-print-prog-name=.*$`: {0, pr.compileUnaryCallback},
`^-print-file-name=.*$`: {0, pr.compileUnaryCallback},
`^-mstack-alignment=.+$`: {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
`^-march=.+$`: {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
`^-mregparm=.+$`: {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
`^-mcmodel=.+$`: {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
`^-mpreferred-stack-boundary=.+$`: {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
`^-mindirect-branch=.+$`: {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
`^--param=.+$`: {0, pr.compileUnaryCallback}, //iam: linux kernel stuff
}
for len(argList) > 0 {
@ -266,17 +287,23 @@ func parse(argList []string) parserResult {
// Else try to match a pattern
} else {
var listShift = 0
var matched = false
for pattern, fi := range argPatterns {
var regExp = regexp.MustCompile(pattern)
if regExp.MatchString(elem) {
fi.handler(elem, argList[1:1+fi.arity])
listShift = fi.arity
matched = true
break
}
}
if !matched {
LogWarning("Did not recognize the compiler flag: %v\n", elem)
//LogWarning("CC %v\n", pr.InputList)
pr.compileUnaryCallback(elem, argList[1:1])
}
argList = argList[1+listShift:]
}
}
return pr
}

View File

@ -35,6 +35,7 @@ package shared
import (
"bytes"
"flag"
"os"
"os/exec"
"path/filepath"
@ -87,6 +88,10 @@ then LLVM_AR_NAME should be set to llvm-ar-3.5.
`
type sanityArgs struct {
Environment bool
}
// SanityCheck performs the environmental sanity check.
//
// Performs the following checks in order:
@ -98,8 +103,14 @@ then LLVM_AR_NAME should be set to llvm-ar-3.5.
//
func SanityCheck() {
sa := parseSanitySwitches()
LogWrite("\nVersion info: gsanity-check version %v\nReleased: %v\n", gllvmVersion, gllvmReleaseDate)
if sa.Environment {
printEnvironment()
}
checkLogging()
checkOS()
@ -116,6 +127,20 @@ func SanityCheck() {
}
func parseSanitySwitches() (sa sanityArgs) {
sa = sanityArgs{
Environment: false,
}
environmentPtr := flag.Bool("e", false, "show environment")
flag.Parse()
sa.Environment = *environmentPtr
return
}
func checkOS() {
platform := runtime.GOOS
@ -260,6 +285,6 @@ func checkLogging() {
LogWrite("Logging level is set to UNKNOWN level %s, using default of ERROR.\n\n", LLVMLoggingLevel)
}
} else {
LogWrite("Logging level not set, using default of ERROR.\n\n")
LogWrite("Logging level not set, using default of WARNING.\n\n")
}
}

View File

@ -34,6 +34,7 @@
package shared
import (
"bytes"
"os"
"os/exec"
)
@ -57,3 +58,19 @@ func execCmd(cmdExecName string, args []string, workingDir string) (success bool
success = (ecode == 0)
return
}
// Executes a command then returns the output as a string, err is either nil or the error.
func runCmd(cmdExecName string, args []string) (output string, err error) {
var outb bytes.Buffer
var errb bytes.Buffer
cmd := exec.Command(cmdExecName, args...)
cmd.Stdout = &outb
cmd.Stderr = &errb
cmd.Stdin = os.Stdin
err = cmd.Run()
if err != nil {
LogDebug("runCmd: error was %v\n", err)
}
output = outb.String()
return
}