Skip to content

Commit 70a9d23

Browse files
committed
2 parents b59676b + 44b352b commit 70a9d23

File tree

6 files changed

+164
-22
lines changed

6 files changed

+164
-22
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ lint:
3030
golint ./shared/ ./tests/ ./cmd/...
3131

3232
clean:
33-
rm -f data/hello data/hello.bc [td]*/.helloworld.c.o [td]*/.helloworld.c.o.bc
33+
rm -f data/*hello data/*.bc [td]*/.*.c.o [td]*/*.o [td]*/.*.c.o.bc data/*.notanextensionthatwerecognize

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,12 @@ such as *link time optimization* (indicated by the presence of compiler flag `-f
250250
your build is unlikely to produce anything that `get-bc` will work on. This is to be
251251
expected.
252252

253+
## Developer tools
253254

255+
Debugging usually boils down to looking in the logs, maybe adding a print statement or two.
256+
There is an additional executable, not mentioned above, called `gparse` that gets installed
257+
along with `gclang`, `gclang++`, `get-bc` and `gsanity-check`. `gparse` takes the command line
258+
arguments to the compiler, and outputs how it parsed them. This can sometimes be helpful.
254259

255260
## License
256261

shared/compiler.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ func attachBitcodePathToObject(bcFile, objFile string) (success bool) {
153153
default:
154154
//OK we have to work harder here
155155
ok, err := injectableViaFileType(objFile)
156+
LogDebug("attachBitcodePathToObject: injectableViaFileType returned ok=%v err=%v", ok, err)
156157
if ok {
157158
success = injectPath(extension, bcFile, objFile)
158159
return
@@ -161,6 +162,7 @@ func attachBitcodePathToObject(bcFile, objFile string) (success bool) {
161162
// OK we have to work EVEN harder here (the file utility is not installed - probably)
162163
// N.B. this will probably fail if we are cross compiling.
163164
ok, err = injectableViaDebug(objFile)
165+
LogDebug("attachBitcodePathToObject: injectableViaDebug returned ok=%v err=%v", ok, err)
164166
if ok {
165167
success = injectPath(extension, bcFile, objFile)
166168
return
@@ -269,6 +271,7 @@ func compileTimeLinkFiles(compilerExecName string, pr ParserResult, objFiles []s
269271
func buildObjectFile(compilerExecName string, pr ParserResult, srcFile string, objFile string) (success bool) {
270272
args := pr.CompileArgs[:]
271273
args = append(args, srcFile, "-c", "-o", objFile)
274+
LogDebug("buildObjectFile: %v", args)
272275
success, err := execCmd(compilerExecName, args, "")
273276
if !success {
274277
LogError("Failed to build object file for %s because: %v\n", srcFile, err)

shared/filetypes.go

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import (
4242
"strings"
4343
)
4444

45-
//BinaryType is the 'intersection' of elf.Type and macho.Type and partitions
45+
// BinaryType is the 'intersection' of elf.Type and macho.Type and partitions
4646
// the binary world into categories we are most interested in. Missing is
4747
// ARCHIVE but that is because it is not an elf format, so we cannot entirely
4848
// eliminate the use of the 'file' utility (cf getFileType below).
@@ -59,6 +59,49 @@ const (
5959
BinaryShared BinaryType = 3
6060
)
6161

62+
func (bt BinaryType) String() string {
63+
switch bt {
64+
case BinaryUnknown:
65+
return "Unknown"
66+
case BinaryObject:
67+
return "Object"
68+
case BinaryExecutable:
69+
return "Executable"
70+
case BinaryShared:
71+
return "Library"
72+
default:
73+
return "Error"
74+
}
75+
}
76+
77+
// GetBinaryType gets the binary type of the given path
78+
func GetBinaryType(path string) (bt BinaryType) {
79+
bt = BinaryUnknown
80+
plain := IsPlainFile(path)
81+
if !plain {
82+
return
83+
}
84+
// try the format that suits the platform first
85+
operatingSys := runtime.GOOS
86+
switch operatingSys {
87+
case "linux", "freebsd":
88+
bt, _ = ElfFileType(path)
89+
case "darwin":
90+
bt, _ = MachoFileType(path)
91+
}
92+
if bt != BinaryUnknown {
93+
return
94+
}
95+
// try the other format instead
96+
switch operatingSys {
97+
case "linux", "freebsd":
98+
bt, _ = MachoFileType(path)
99+
case "darwin":
100+
bt, _ = ElfFileType(path)
101+
}
102+
return
103+
}
104+
62105
func elfType2BinaryType(et elf.Type) (bt BinaryType) {
63106
bt = BinaryUnknown
64107
switch et {
@@ -95,29 +138,32 @@ func machoType2BinaryType(mt macho.Type) (bt BinaryType) {
95138
return
96139
}
97140

98-
// isPlainFile returns true if the file is stat-able (i.e. exists etc), and is not a directory, else it returns false.
99-
func isPlainFile(objectFile string) (ok bool) {
141+
// IsPlainFile returns true if the file is stat-able (i.e. exists etc), and is not a directory, else it returns false.
142+
func IsPlainFile(objectFile string) (ok bool) {
100143
info, err := os.Stat(objectFile)
101-
if os.IsNotExist(err) || info.IsDir() {
144+
if os.IsNotExist(err) {
102145
return
103146
}
104147
if err != nil {
105148
return
106149
}
150+
if info.IsDir() {
151+
return
152+
}
107153
ok = true
108154
return
109155
}
110156

111157
func injectableViaFileType(objectFile string) (ok bool, err error) {
112-
plain := isPlainFile(objectFile)
158+
plain := IsPlainFile(objectFile)
113159
if !plain {
114160
return
115161
}
116162
fileType, err := getFileType(objectFile)
117163
if err != nil {
118164
return
119165
}
120-
ok = (fileType == fileTypeELFOBJECT) || (fileType == fileTypeELFOBJECT)
166+
ok = (fileType == fileTypeELFOBJECT) || (fileType == fileTypeMACHOBJECT)
121167
return
122168
}
123169

@@ -151,7 +197,7 @@ func MachoFileType(objectFile string) (code BinaryType, err error) {
151197

152198
//IsObjectFileForOS returns true if the given file is an object file for the given OS, using the debug/elf and debug/macho packages.
153199
func IsObjectFileForOS(objectFile string, operatingSys string) (ok bool, err error) {
154-
plain := isPlainFile(objectFile)
200+
plain := IsPlainFile(objectFile)
155201
if !plain {
156202
return
157203
}

shared/parser.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ func Parse(argList []string) ParserResult {
177177
"--version": {0, pr.compileOnlyCallback},
178178
"-v": {0, pr.compileOnlyCallback},
179179

180-
"-w": {0, pr.compileOnlyCallback},
181-
"-W": {0, pr.compileOnlyCallback},
180+
"-w": {0, pr.compileUnaryCallback},
181+
"-W": {0, pr.compileUnaryCallback},
182182

183183
"-emit-llvm": {0, pr.emitLLVMCallback},
184184
"-flto": {0, pr.linkTimeOptimizationCallback},

tests/entry_test.go

Lines changed: 100 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,23 @@ import (
77
"testing"
88
)
99

10+
const (
11+
DEBUG bool = false
12+
)
13+
1014
func Test_basic_functionality(t *testing.T) {
1115
args := []string{"../data/helloworld.c", "-o", "../data/hello"}
1216
exitCode := shared.Compile(args, "clang")
1317
if exitCode != 0 {
1418
t.Errorf("Compile of %v returned %v\n", args, exitCode)
15-
} else {
19+
} else if DEBUG {
1620
fmt.Println("Compiled OK")
1721
}
1822
args = []string{"get-bc", "-v", "../data/hello"}
1923
exitCode = shared.Extract(args)
2024
if exitCode != 0 {
2125
t.Errorf("Extraction of %v returned %v\n", args, exitCode)
22-
} else {
26+
} else if DEBUG {
2327
fmt.Println("Extraction OK")
2428
}
2529
}
@@ -30,27 +34,27 @@ func Test_more_functionality(t *testing.T) {
3034
exitCode := shared.Compile(args, "clang")
3135
if exitCode != 0 {
3236
t.Errorf("Compile of %v returned %v\n", args, exitCode)
33-
} else {
37+
} else if DEBUG {
3438
fmt.Println("Compiled OK")
3539
}
3640
ok, err := shared.IsObjectFileForOS(objectFile, runtime.GOOS)
3741
if !ok {
3842
t.Errorf("isObjectFileForOS(%v, %v) = %v (err = %v)\n", objectFile, runtime.GOOS, ok, err)
39-
} else {
43+
} else if DEBUG {
4044
fmt.Printf("isObjectFileForOS(%v, %v) = %v\n", objectFile, runtime.GOOS, ok)
4145
}
4246
args = []string{objectFile, "-o", "../data/bhello"}
4347
exitCode = shared.Compile(args, "clang")
4448
if exitCode != 0 {
4549
t.Errorf("Compile of %v returned %v\n", args, exitCode)
46-
} else {
50+
} else if DEBUG {
4751
fmt.Println("Compiled OK")
4852
}
4953
args = []string{"get-bc", "-v", "../data/bhello"}
5054
exitCode = shared.Extract(args)
5155
if exitCode != 0 {
5256
t.Errorf("Extraction of %v returned %v\n", args, exitCode)
53-
} else {
57+
} else if DEBUG {
5458
fmt.Println("Extraction OK")
5559
}
5660
}
@@ -64,39 +68,123 @@ func Test_obscure_functionality(t *testing.T) {
6468
exitCode := shared.Compile(args, "clang")
6569
if exitCode != 0 {
6670
t.Errorf("Compile of %v returned %v\n", args, exitCode)
67-
} else {
71+
} else if DEBUG {
6872
fmt.Println("Compiled OK")
6973
}
7074
ok, err := shared.IsObjectFileForOS(sourceFile, opSys)
7175
if ok {
7276
t.Errorf("isObjectFileForOS(%v, %v) = %v\n", sourceFile, opSys, ok)
73-
} else {
77+
} else if DEBUG {
7478
fmt.Printf("isObjectFileForOS(%v, %v) = %v (err = %v)\n", sourceFile, opSys, ok, err)
7579
}
7680
ok, err = shared.IsObjectFileForOS(objectFile, opSys)
7781
if !ok {
7882
t.Errorf("isObjectFileForOS(%v, %v) = %v (err = %v)\n", objectFile, opSys, ok, err)
79-
} else {
83+
} else if DEBUG {
8084
fmt.Printf("isObjectFileForOS(%v, %v) = %v\n", objectFile, opSys, ok)
8185
}
8286
args = []string{objectFile, "-o", exeFile}
8387
exitCode = shared.Compile(args, "clang")
8488
if exitCode != 0 {
8589
t.Errorf("Compile of %v returned %v\n", args, exitCode)
86-
} else {
90+
} else if DEBUG {
8791
fmt.Println("Compiled OK")
8892
}
8993
ok, err = shared.IsObjectFileForOS(exeFile, opSys)
9094
if ok {
9195
t.Errorf("isObjectFileForOS(%v, %v) = %v\n", exeFile, opSys, ok)
92-
} else {
96+
} else if DEBUG {
9397
fmt.Printf("isObjectFileForOS(%v, %v) = %v (err = %v)\n", exeFile, opSys, ok, err)
9498
}
9599
args = []string{"get-bc", "-v", exeFile}
96100
exitCode = shared.Extract(args)
97101
if exitCode != 0 {
98102
t.Errorf("Extraction of %v returned %v\n", args, exitCode)
99-
} else {
103+
} else if DEBUG {
100104
fmt.Println("Extraction OK")
101105
}
102106
}
107+
108+
func Test_file_type(t *testing.T) {
109+
fictionalFile := "HopefullyThereIsNotAFileCalledThisNearBy.txt"
110+
dataDir := "../data"
111+
sourceFile := "../data/helloworld.c"
112+
objectFile := "../data/bhello.notanextensionthatwerecognize"
113+
exeFile := "../data/bhello"
114+
115+
var binaryFileType shared.BinaryType
116+
binaryFileType = shared.GetBinaryType(fictionalFile)
117+
118+
if binaryFileType != shared.BinaryUnknown {
119+
t.Errorf("GetBinaryType(%v) = %v\n", fictionalFile, binaryFileType)
120+
} else if DEBUG {
121+
fmt.Printf("GetBinaryType(%v) = %v\n", fictionalFile, binaryFileType)
122+
}
123+
124+
binaryFileType = shared.GetBinaryType(dataDir)
125+
126+
if binaryFileType != shared.BinaryUnknown {
127+
t.Errorf("GetBinaryType(%v) = %v\n", dataDir, binaryFileType)
128+
} else if DEBUG {
129+
fmt.Printf("GetBinaryType(%v) = %v\n", dataDir, binaryFileType)
130+
}
131+
132+
binaryFileType = shared.GetBinaryType(sourceFile)
133+
if binaryFileType != shared.BinaryUnknown {
134+
t.Errorf("GetBinaryType(%v) = %v\n", sourceFile, binaryFileType)
135+
} else if DEBUG {
136+
fmt.Printf("GetBinaryType(%v) = %v\n", sourceFile, binaryFileType)
137+
}
138+
139+
binaryFileType = shared.GetBinaryType(objectFile)
140+
if binaryFileType != shared.BinaryObject {
141+
t.Errorf("GetBinaryType(%v) = %v\n", objectFile, binaryFileType)
142+
} else if DEBUG {
143+
fmt.Printf("GetBinaryType(%v) = %v\n", objectFile, binaryFileType)
144+
}
145+
146+
binaryFileType = shared.GetBinaryType(exeFile)
147+
if binaryFileType != shared.BinaryExecutable {
148+
t.Errorf("GetBinaryType(%v) = %v\n", exeFile, binaryFileType)
149+
} else if DEBUG {
150+
fmt.Printf("GetBinaryType(%v) = %v\n", exeFile, binaryFileType)
151+
}
152+
153+
var plain bool
154+
plain = shared.IsPlainFile(fictionalFile)
155+
156+
if plain {
157+
t.Errorf("shared.IsPlainFile(%v) returned %v\n", fictionalFile, plain)
158+
} else if DEBUG {
159+
fmt.Printf("shared.IsPlainFile(%v) returned %v\n", fictionalFile, plain)
160+
}
161+
162+
plain = shared.IsPlainFile(dataDir)
163+
if plain {
164+
t.Errorf("shared.IsPlainFile(%v) returned %v\n", dataDir, plain)
165+
} else if DEBUG {
166+
fmt.Printf("shared.IsPlainFile(%v) returned %v\n", dataDir, plain)
167+
}
168+
169+
plain = shared.IsPlainFile(sourceFile)
170+
if !plain {
171+
t.Errorf("shared.IsPlainFile(%v) returned %v\n", sourceFile, plain)
172+
} else if DEBUG {
173+
fmt.Printf("shared.IsPlainFile(%v) returned %v\n", sourceFile, plain)
174+
}
175+
176+
plain = shared.IsPlainFile(objectFile)
177+
if !plain {
178+
t.Errorf("shared.IsPlainFile(%v) returned %v\n", objectFile, plain)
179+
} else if DEBUG {
180+
fmt.Printf("shared.IsPlainFile(%v) returned %v\n", objectFile, plain)
181+
}
182+
183+
plain = shared.IsPlainFile(exeFile)
184+
if !plain {
185+
t.Errorf("shared.IsPlainFile(%v) returned %v\n", exeFile, plain)
186+
} else if DEBUG {
187+
fmt.Printf("shared.IsPlainFile(%v) returned %v\n", exeFile, plain)
188+
}
189+
190+
}

0 commit comments

Comments
 (0)