From beca29f43d356bc7b858fc9ff2c7af82384269e4 Mon Sep 17 00:00:00 2001 From: "Ian A.Mason" Date: Sat, 31 Oct 2020 11:33:08 -0700 Subject: [PATCH 1/9] =?UTF-8?q?Typo=20\=5F(=E3=83=84)=5F/=C2=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/compiler.go | 2 ++ shared/filetypes.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/shared/compiler.go b/shared/compiler.go index 5d7df99..8c5fcc3 100644 --- a/shared/compiler.go +++ b/shared/compiler.go @@ -153,6 +153,7 @@ func attachBitcodePathToObject(bcFile, objFile string) (success bool) { default: //OK we have to work harder here ok, err := injectableViaFileType(objFile) + LogDebug("attachBitcodePathToObject: injectableViaFileType returned ok=%v err=%v", ok, err) if ok { success = injectPath(extension, bcFile, objFile) return @@ -161,6 +162,7 @@ func attachBitcodePathToObject(bcFile, objFile string) (success bool) { // OK we have to work EVEN harder here (the file utility is not installed - probably) // N.B. this will probably fail if we are cross compiling. ok, err = injectableViaDebug(objFile) + LogDebug("attachBitcodePathToObject: injectableViaDebug returned ok=%v err=%v", ok, err) if ok { success = injectPath(extension, bcFile, objFile) return diff --git a/shared/filetypes.go b/shared/filetypes.go index 41df092..f868d56 100644 --- a/shared/filetypes.go +++ b/shared/filetypes.go @@ -117,7 +117,7 @@ func injectableViaFileType(objectFile string) (ok bool, err error) { if err != nil { return } - ok = (fileType == fileTypeELFOBJECT) || (fileType == fileTypeELFOBJECT) + ok = (fileType == fileTypeELFOBJECT) || (fileType == fileTypeMACHOBJECT) return } From 4f6a8f5d575e264e09ac574b9be0a4c441143521 Mon Sep 17 00:00:00 2001 From: "Ian A.Mason" Date: Sun, 1 Nov 2020 10:49:22 -0800 Subject: [PATCH 2/9] Polishing the file type stuff, and adding a test or two, for prosperity. --- shared/filetypes.go | 53 ++++++++++++++++++++++++++++++++++++++++----- tests/entry_test.go | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/shared/filetypes.go b/shared/filetypes.go index f868d56..63e582e 100644 --- a/shared/filetypes.go +++ b/shared/filetypes.go @@ -42,7 +42,7 @@ import ( "strings" ) -//BinaryType is the 'intersection' of elf.Type and macho.Type and partitions +// BinaryType is the 'intersection' of elf.Type and macho.Type and partitions // the binary world into categories we are most interested in. Missing is // ARCHIVE but that is because it is not an elf format, so we cannot entirely // eliminate the use of the 'file' utility (cf getFileType below). @@ -59,6 +59,49 @@ const ( BinaryShared BinaryType = 3 ) +func (bt BinaryType) String() string { + switch bt { + case BinaryUnknown: + return "Unknown" + case BinaryObject: + return "Object" + case BinaryExecutable: + return "Executable" + case BinaryShared: + return "Library" + default: + return "Error" + } +} + +// GetBinaryType gets the binary type of the given path +func GetBinaryType(path string) (bt BinaryType) { + bt = BinaryUnknown + plain := IsPlainFile(path) + if !plain { + return + } + // try the format that suits the platform first + operatingSys := runtime.GOOS + switch operatingSys { + case "linux", "freebsd": + bt, _ = ElfFileType(path) + case "darwin": + bt, _ = MachoFileType(path) + } + if bt != BinaryUnknown { + return + } + // try the other format instead + switch operatingSys { + case "linux", "freebsd": + bt, _ = MachoFileType(path) + case "darwin": + bt, _ = ElfFileType(path) + } + return +} + func elfType2BinaryType(et elf.Type) (bt BinaryType) { bt = BinaryUnknown switch et { @@ -95,8 +138,8 @@ func machoType2BinaryType(mt macho.Type) (bt BinaryType) { return } -// isPlainFile returns true if the file is stat-able (i.e. exists etc), and is not a directory, else it returns false. -func isPlainFile(objectFile string) (ok bool) { +// IsPlainFile returns true if the file is stat-able (i.e. exists etc), and is not a directory, else it returns false. +func IsPlainFile(objectFile string) (ok bool) { info, err := os.Stat(objectFile) if os.IsNotExist(err) || info.IsDir() { return @@ -109,7 +152,7 @@ func isPlainFile(objectFile string) (ok bool) { } func injectableViaFileType(objectFile string) (ok bool, err error) { - plain := isPlainFile(objectFile) + plain := IsPlainFile(objectFile) if !plain { return } @@ -151,7 +194,7 @@ func MachoFileType(objectFile string) (code BinaryType, err error) { //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) + plain := IsPlainFile(objectFile) if !plain { return } diff --git a/tests/entry_test.go b/tests/entry_test.go index 5eca10a..41cf5e1 100644 --- a/tests/entry_test.go +++ b/tests/entry_test.go @@ -100,3 +100,48 @@ func Test_obscure_functionality(t *testing.T) { fmt.Println("Extraction OK") } } + +func Test_file_type(t *testing.T) { + fictionalFile := "HopefullyThereIsNotAFileCalledThisNearBy.txt" + dataDir := "../data" + sourceFile := "../data/helloworld.c" + objectFile := "../data/bhello.notanextensionthatwerecognize" + exeFile := "../data/bhello" + fmt.Printf("GetBinaryType(%v) = %v\n", fictionalFile, shared.GetBinaryType(fictionalFile)) + fmt.Printf("GetBinaryType(%v) = %v\n", dataDir, shared.GetBinaryType(dataDir)) + fmt.Printf("GetBinaryType(%v) = %v\n", sourceFile, shared.GetBinaryType(sourceFile)) + fmt.Printf("GetBinaryType(%v) = %v\n", objectFile, shared.GetBinaryType(objectFile)) + fmt.Printf("GetBinaryType(%v) = %v\n", exeFile, shared.GetBinaryType(exeFile)) + + plain := shared.IsPlainFile(fictionalFile) + if plain { + t.Errorf("shared.IsPlainFile(%v) returned %v\n", fictionalFile, plain) + } else { + fmt.Printf("shared.IsPlainFile(%v) returned %v\n", fictionalFile, plain) + } + plain = shared.IsPlainFile(dataDir) + if plain { + t.Errorf("shared.IsPlainFile(%v) returned %v\n", dataDir, plain) + } else { + fmt.Printf("shared.IsPlainFile(%v) returned %v\n", dataDir, plain) + } + plain = shared.IsPlainFile(sourceFile) + if !plain { + t.Errorf("shared.IsPlainFile(%v) returned %v\n", sourceFile, plain) + } else { + fmt.Printf("shared.IsPlainFile(%v) returned %v\n", sourceFile, plain) + } + plain = shared.IsPlainFile(objectFile) + if !plain { + t.Errorf("shared.IsPlainFile(%v) returned %v\n", objectFile, plain) + } else { + fmt.Printf("shared.IsPlainFile(%v) returned %v\n", objectFile, plain) + } + plain = shared.IsPlainFile(exeFile) + if !plain { + t.Errorf("shared.IsPlainFile(%v) returned %v\n", exeFile, plain) + } else { + fmt.Printf("shared.IsPlainFile(%v) returned %v\n", exeFile, plain) + } + +} From 78dee1604d439e4aec7cb81010f667cb8636abec Mon Sep 17 00:00:00 2001 From: "Ian A.Mason" Date: Sun, 1 Nov 2020 18:55:14 -0800 Subject: [PATCH 3/9] Test clean up. --- Makefile | 2 +- shared/filetypes.go | 5 ++- tests/entry_test.go | 89 +++++++++++++++++++++++++++++++++------------ 3 files changed, 71 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index f64adc4..f2a12fc 100644 --- a/Makefile +++ b/Makefile @@ -30,4 +30,4 @@ lint: golint ./shared/ ./tests/ ./cmd/... clean: - rm -f data/hello data/hello.bc [td]*/.helloworld.c.o [td]*/.helloworld.c.o.bc + rm -f data/*hello data/*.bc [td]*/.*.c.o [td]*/*.o [td]*/.*.c.o.bc data/*.notanextensionthatwerecognize diff --git a/shared/filetypes.go b/shared/filetypes.go index 63e582e..ef9167e 100644 --- a/shared/filetypes.go +++ b/shared/filetypes.go @@ -141,12 +141,15 @@ func machoType2BinaryType(mt macho.Type) (bt BinaryType) { // IsPlainFile returns true if the file is stat-able (i.e. exists etc), and is not a directory, else it returns false. func IsPlainFile(objectFile string) (ok bool) { info, err := os.Stat(objectFile) - if os.IsNotExist(err) || info.IsDir() { + if os.IsNotExist(err) { return } if err != nil { return } + if info.IsDir() { + return + } ok = true return } diff --git a/tests/entry_test.go b/tests/entry_test.go index 41cf5e1..0abd9c3 100644 --- a/tests/entry_test.go +++ b/tests/entry_test.go @@ -7,19 +7,23 @@ import ( "testing" ) +const ( + DEBUG bool = false +) + func Test_basic_functionality(t *testing.T) { args := []string{"../data/helloworld.c", "-o", "../data/hello"} exitCode := shared.Compile(args, "clang") if exitCode != 0 { t.Errorf("Compile of %v returned %v\n", args, exitCode) - } else { + } else if DEBUG { fmt.Println("Compiled OK") } args = []string{"get-bc", "-v", "../data/hello"} exitCode = shared.Extract(args) if exitCode != 0 { t.Errorf("Extraction of %v returned %v\n", args, exitCode) - } else { + } else if DEBUG { fmt.Println("Extraction OK") } } @@ -30,27 +34,27 @@ func Test_more_functionality(t *testing.T) { exitCode := shared.Compile(args, "clang") if exitCode != 0 { t.Errorf("Compile of %v returned %v\n", args, exitCode) - } else { + } else if DEBUG { fmt.Println("Compiled OK") } ok, err := shared.IsObjectFileForOS(objectFile, runtime.GOOS) if !ok { t.Errorf("isObjectFileForOS(%v, %v) = %v (err = %v)\n", objectFile, runtime.GOOS, ok, err) - } else { + } else if DEBUG { fmt.Printf("isObjectFileForOS(%v, %v) = %v\n", objectFile, runtime.GOOS, ok) } args = []string{objectFile, "-o", "../data/bhello"} exitCode = shared.Compile(args, "clang") if exitCode != 0 { t.Errorf("Compile of %v returned %v\n", args, exitCode) - } else { + } else if DEBUG { fmt.Println("Compiled OK") } args = []string{"get-bc", "-v", "../data/bhello"} exitCode = shared.Extract(args) if exitCode != 0 { t.Errorf("Extraction of %v returned %v\n", args, exitCode) - } else { + } else if DEBUG { fmt.Println("Extraction OK") } } @@ -64,39 +68,39 @@ func Test_obscure_functionality(t *testing.T) { exitCode := shared.Compile(args, "clang") if exitCode != 0 { t.Errorf("Compile of %v returned %v\n", args, exitCode) - } else { + } else if DEBUG { fmt.Println("Compiled OK") } ok, err := shared.IsObjectFileForOS(sourceFile, opSys) if ok { t.Errorf("isObjectFileForOS(%v, %v) = %v\n", sourceFile, opSys, ok) - } else { + } else if DEBUG { fmt.Printf("isObjectFileForOS(%v, %v) = %v (err = %v)\n", sourceFile, opSys, ok, err) } ok, err = shared.IsObjectFileForOS(objectFile, opSys) if !ok { t.Errorf("isObjectFileForOS(%v, %v) = %v (err = %v)\n", objectFile, opSys, ok, err) - } else { + } else if DEBUG { fmt.Printf("isObjectFileForOS(%v, %v) = %v\n", objectFile, opSys, ok) } args = []string{objectFile, "-o", exeFile} exitCode = shared.Compile(args, "clang") if exitCode != 0 { t.Errorf("Compile of %v returned %v\n", args, exitCode) - } else { + } else if DEBUG { fmt.Println("Compiled OK") } ok, err = shared.IsObjectFileForOS(exeFile, opSys) if ok { t.Errorf("isObjectFileForOS(%v, %v) = %v\n", exeFile, opSys, ok) - } else { + } else if DEBUG { fmt.Printf("isObjectFileForOS(%v, %v) = %v (err = %v)\n", exeFile, opSys, ok, err) } args = []string{"get-bc", "-v", exeFile} exitCode = shared.Extract(args) if exitCode != 0 { t.Errorf("Extraction of %v returned %v\n", args, exitCode) - } else { + } else if DEBUG { fmt.Println("Extraction OK") } } @@ -107,40 +111,79 @@ func Test_file_type(t *testing.T) { sourceFile := "../data/helloworld.c" objectFile := "../data/bhello.notanextensionthatwerecognize" exeFile := "../data/bhello" - fmt.Printf("GetBinaryType(%v) = %v\n", fictionalFile, shared.GetBinaryType(fictionalFile)) - fmt.Printf("GetBinaryType(%v) = %v\n", dataDir, shared.GetBinaryType(dataDir)) - fmt.Printf("GetBinaryType(%v) = %v\n", sourceFile, shared.GetBinaryType(sourceFile)) - fmt.Printf("GetBinaryType(%v) = %v\n", objectFile, shared.GetBinaryType(objectFile)) - fmt.Printf("GetBinaryType(%v) = %v\n", exeFile, shared.GetBinaryType(exeFile)) - plain := shared.IsPlainFile(fictionalFile) + var binaryFileType shared.BinaryType + binaryFileType = shared.GetBinaryType(fictionalFile) + + if binaryFileType != shared.BinaryUnknown { + t.Errorf("GetBinaryType(%v) = %v\n", fictionalFile, binaryFileType) + } else if DEBUG { + fmt.Printf("GetBinaryType(%v) = %v\n", fictionalFile, binaryFileType) + } + + binaryFileType = shared.GetBinaryType(dataDir) + + if binaryFileType != shared.BinaryUnknown { + t.Errorf("GetBinaryType(%v) = %v\n", dataDir, binaryFileType) + } else if DEBUG { + fmt.Printf("GetBinaryType(%v) = %v\n", dataDir, binaryFileType) + } + + binaryFileType = shared.GetBinaryType(sourceFile) + if binaryFileType != shared.BinaryUnknown { + t.Errorf("GetBinaryType(%v) = %v\n", sourceFile, binaryFileType) + } else if DEBUG { + fmt.Printf("GetBinaryType(%v) = %v\n", sourceFile, binaryFileType) + } + + binaryFileType = shared.GetBinaryType(objectFile) + if binaryFileType != shared.BinaryObject { + t.Errorf("GetBinaryType(%v) = %v\n", objectFile, binaryFileType) + } else if DEBUG { + fmt.Printf("GetBinaryType(%v) = %v\n", objectFile, binaryFileType) + } + + binaryFileType = shared.GetBinaryType(exeFile) + if binaryFileType != shared.BinaryExecutable { + t.Errorf("GetBinaryType(%v) = %v\n", exeFile, binaryFileType) + } else if DEBUG { + fmt.Printf("GetBinaryType(%v) = %v\n", exeFile, binaryFileType) + } + + var plain bool + plain = shared.IsPlainFile(fictionalFile) + if plain { t.Errorf("shared.IsPlainFile(%v) returned %v\n", fictionalFile, plain) - } else { + } else if DEBUG { fmt.Printf("shared.IsPlainFile(%v) returned %v\n", fictionalFile, plain) } + plain = shared.IsPlainFile(dataDir) if plain { t.Errorf("shared.IsPlainFile(%v) returned %v\n", dataDir, plain) - } else { + } else if DEBUG { fmt.Printf("shared.IsPlainFile(%v) returned %v\n", dataDir, plain) } + plain = shared.IsPlainFile(sourceFile) if !plain { t.Errorf("shared.IsPlainFile(%v) returned %v\n", sourceFile, plain) - } else { + } else if DEBUG { fmt.Printf("shared.IsPlainFile(%v) returned %v\n", sourceFile, plain) } + plain = shared.IsPlainFile(objectFile) if !plain { t.Errorf("shared.IsPlainFile(%v) returned %v\n", objectFile, plain) - } else { + } else if DEBUG { fmt.Printf("shared.IsPlainFile(%v) returned %v\n", objectFile, plain) } + plain = shared.IsPlainFile(exeFile) if !plain { t.Errorf("shared.IsPlainFile(%v) returned %v\n", exeFile, plain) - } else { + } else if DEBUG { fmt.Printf("shared.IsPlainFile(%v) returned %v\n", exeFile, plain) } From 70883e356e697df5fa114d1d48aaacb2d4c82a62 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 18 Feb 2021 10:39:32 -0500 Subject: [PATCH 4/9] shared/compiler: add some debug logs --- shared/compiler.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shared/compiler.go b/shared/compiler.go index 8c5fcc3..a1da3a5 100644 --- a/shared/compiler.go +++ b/shared/compiler.go @@ -119,6 +119,7 @@ func buildAndAttachBitcode(compilerExecName string, pr ParserResult, bcObjLinks for i, srcFile := range pr.InputFiles { objFile, bcFile := getArtifactNames(pr, i, hidden) if hidden { + LogDebug("not compile only; building object files") buildObjectFile(compilerExecName, pr, srcFile, objFile) *newObjectFiles = append(*newObjectFiles, objFile) } @@ -271,6 +272,7 @@ func compileTimeLinkFiles(compilerExecName string, pr ParserResult, objFiles []s func buildObjectFile(compilerExecName string, pr ParserResult, srcFile string, objFile string) (success bool) { args := pr.CompileArgs[:] args = append(args, srcFile, "-c", "-o", objFile) + LogDebug("buildObjectFile: %v", args) success, err := execCmd(compilerExecName, args, "") if !success { LogError("Failed to build object file for %s because: %v\n", srcFile, err) From c302d052827a0f01536502ea1d739d827348dadb Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 18 Feb 2021 11:25:11 -0500 Subject: [PATCH 5/9] shared/parser: continued debugging --- shared/parser.go | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/parser.go b/shared/parser.go index 0ca66bd..213a8d2 100644 --- a/shared/parser.go +++ b/shared/parser.go @@ -541,6 +541,7 @@ func (pr *ParserResult) verboseFlagCallback(_ string, _ []string) { } func (pr *ParserResult) compileOnlyCallback(_ string, _ []string) { + LogDebug("compileOnlyCallback") pr.IsCompileOnly = true } From 58e909d35e01377f642eb7e8e1267d49e8384005 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 18 Feb 2021 11:28:56 -0500 Subject: [PATCH 6/9] shared/parser: temporarily disable some callbacks --- shared/parser.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/parser.go b/shared/parser.go index 213a8d2..92a553a 100644 --- a/shared/parser.go +++ b/shared/parser.go @@ -177,8 +177,8 @@ func Parse(argList []string) ParserResult { "--version": {0, pr.compileOnlyCallback}, "-v": {0, pr.compileOnlyCallback}, - "-w": {0, pr.compileOnlyCallback}, - "-W": {0, pr.compileOnlyCallback}, + // "-w": {0, pr.compileOnlyCallback}, + // "-W": {0, pr.compileOnlyCallback}, "-emit-llvm": {0, pr.emitLLVMCallback}, "-flto": {0, pr.linkTimeOptimizationCallback}, From 2607b2c9f026a197aa96f0308ed8694d8893533b Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 18 Feb 2021 11:41:46 -0500 Subject: [PATCH 7/9] shared/parser: use compileUnaryCallback --- shared/parser.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/parser.go b/shared/parser.go index 92a553a..212e250 100644 --- a/shared/parser.go +++ b/shared/parser.go @@ -177,8 +177,8 @@ func Parse(argList []string) ParserResult { "--version": {0, pr.compileOnlyCallback}, "-v": {0, pr.compileOnlyCallback}, - // "-w": {0, pr.compileOnlyCallback}, - // "-W": {0, pr.compileOnlyCallback}, + "-w": {0, pr.compileUnaryCallback}, + "-W": {0, pr.compileUnaryCallback}, "-emit-llvm": {0, pr.emitLLVMCallback}, "-flto": {0, pr.linkTimeOptimizationCallback}, From 285070d09ae4bafa8d4fd6df46b7c0f6c5b79dd0 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 18 Feb 2021 11:45:12 -0500 Subject: [PATCH 8/9] shared: drop some debug logs --- shared/compiler.go | 1 - shared/parser.go | 1 - 2 files changed, 2 deletions(-) diff --git a/shared/compiler.go b/shared/compiler.go index a1da3a5..cd01162 100644 --- a/shared/compiler.go +++ b/shared/compiler.go @@ -119,7 +119,6 @@ func buildAndAttachBitcode(compilerExecName string, pr ParserResult, bcObjLinks for i, srcFile := range pr.InputFiles { objFile, bcFile := getArtifactNames(pr, i, hidden) if hidden { - LogDebug("not compile only; building object files") buildObjectFile(compilerExecName, pr, srcFile, objFile) *newObjectFiles = append(*newObjectFiles, objFile) } diff --git a/shared/parser.go b/shared/parser.go index 212e250..e1383a6 100644 --- a/shared/parser.go +++ b/shared/parser.go @@ -541,7 +541,6 @@ func (pr *ParserResult) verboseFlagCallback(_ string, _ []string) { } func (pr *ParserResult) compileOnlyCallback(_ string, _ []string) { - LogDebug("compileOnlyCallback") pr.IsCompileOnly = true } From 35f6889428e9e8856c774d88b08ee8d8be4d7997 Mon Sep 17 00:00:00 2001 From: Ian A Mason Date: Thu, 18 Feb 2021 09:22:38 -0800 Subject: [PATCH 9/9] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 3a5a0f4..95bffcc 100644 --- a/README.md +++ b/README.md @@ -250,7 +250,12 @@ such as *link time optimization* (indicated by the presence of compiler flag `-f your build is unlikely to produce anything that `get-bc` will work on. This is to be expected. +## Developer tools +Debugging usually boils down to looking in the logs, maybe adding a print statement or two. +There is an additional executable, not mentioned above, called `gparse` that gets installed +along with `gclang`, `gclang++`, `get-bc` and `gsanity-check`. `gparse` takes the command line +arguments to the compiler, and outputs how it parsed them. This can sometimes be helpful. ## License