├── .gitignore
├── laboratory
├── sum.bc
├── main.bc
├── sum.c
├── Makefile
├── main.c
├── sum.ll
└── main.ll
├── Mutang.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── project.pbxproj
├── README.md
└── Mutang
└── main.m
/.gitignore:
--------------------------------------------------------------------------------
1 | Mutang.xcodeproj/xcuserdata
2 | Mutang.xcodeproj/project.xcworkspace/xcuserdata
3 |
--------------------------------------------------------------------------------
/laboratory/sum.bc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlexDenisov/mutation-testing-poc/HEAD/laboratory/sum.bc
--------------------------------------------------------------------------------
/laboratory/main.bc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlexDenisov/mutation-testing-poc/HEAD/laboratory/main.bc
--------------------------------------------------------------------------------
/laboratory/sum.c:
--------------------------------------------------------------------------------
1 | int someUnusedFucntion() {
2 | return 42.f;
3 | }
4 |
5 | int sum(int a, int b) {
6 | return a + b;
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/laboratory/Makefile:
--------------------------------------------------------------------------------
1 | CC=~/Projects/LLVM/build_static/bin/clang
2 |
3 | all:
4 | $(CC) -c -emit-llvm -g main.c sum.c
5 | $(CC) -S -emit-llvm -gline-tables-only main.c sum.c
6 |
--------------------------------------------------------------------------------
/laboratory/main.c:
--------------------------------------------------------------------------------
1 | extern int sum(int a, int b);
2 |
3 | int test_main() {
4 | int result = sum(3, 5);
5 | int result_matches = result == 8;
6 |
7 | return result_matches;
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/Mutang.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/laboratory/sum.ll:
--------------------------------------------------------------------------------
1 | ; ModuleID = 'sum.c'
2 | target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
3 | target triple = "x86_64-apple-macosx10.11.0"
4 |
5 | ; Function Attrs: nounwind ssp uwtable
6 | define i32 @someUnusedFucntion() #0 !dbg !4 {
7 | entry:
8 | ret i32 42, !dbg !11
9 | }
10 |
11 | ; Function Attrs: nounwind ssp uwtable
12 | define i32 @sum(i32 %a, i32 %b) #0 !dbg !6 {
13 | entry:
14 | %a.addr = alloca i32, align 4
15 | %b.addr = alloca i32, align 4
16 | store i32 %a, i32* %a.addr, align 4
17 | store i32 %b, i32* %b.addr, align 4
18 | %0 = load i32, i32* %a.addr, align 4, !dbg !12
19 | %1 = load i32, i32* %b.addr, align 4, !dbg !13
20 | %add = add nsw i32 %0, %1, !dbg !14
21 | ret i32 %add, !dbg !15
22 | }
23 |
24 | attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
25 |
26 | !llvm.dbg.cu = !{!0}
27 | !llvm.module.flags = !{!7, !8, !9}
28 | !llvm.ident = !{!10}
29 |
30 | !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)", isOptimized: false, runtimeVersion: 0, emissionKind: 2, enums: !2, subprograms: !3)
31 | !1 = !DIFile(filename: "sum.c", directory: "/Users/alexdenisov/Projects/LLVM/Mutang/laboratory")
32 | !2 = !{}
33 | !3 = !{!4, !6}
34 | !4 = distinct !DISubprogram(name: "someUnusedFucntion", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, variables: !2)
35 | !5 = !DISubroutineType(types: !2)
36 | !6 = distinct !DISubprogram(name: "sum", scope: !1, file: !1, line: 5, type: !5, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false, variables: !2)
37 | !7 = !{i32 2, !"Dwarf Version", i32 2}
38 | !8 = !{i32 2, !"Debug Info Version", i32 3}
39 | !9 = !{i32 1, !"PIC Level", i32 2}
40 | !10 = !{!"clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)"}
41 | !11 = !DILocation(line: 2, column: 3, scope: !4)
42 | !12 = !DILocation(line: 6, column: 10, scope: !6)
43 | !13 = !DILocation(line: 6, column: 14, scope: !6)
44 | !14 = !DILocation(line: 6, column: 12, scope: !6)
45 | !15 = !DILocation(line: 6, column: 3, scope: !6)
46 |
--------------------------------------------------------------------------------
/laboratory/main.ll:
--------------------------------------------------------------------------------
1 | ; ModuleID = 'main.c'
2 | target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
3 | target triple = "x86_64-apple-macosx10.11.0"
4 |
5 | ; Function Attrs: nounwind ssp uwtable
6 | define i32 @test_main() #0 !dbg !4 {
7 | entry:
8 | %result = alloca i32, align 4
9 | %result_matches = alloca i32, align 4
10 | %call = call i32 @sum(i32 3, i32 5), !dbg !10
11 | store i32 %call, i32* %result, align 4, !dbg !11
12 | %0 = load i32, i32* %result, align 4, !dbg !12
13 | %cmp = icmp eq i32 %0, 8, !dbg !13
14 | %conv = zext i1 %cmp to i32, !dbg !13
15 | store i32 %conv, i32* %result_matches, align 4, !dbg !14
16 | %1 = load i32, i32* %result_matches, align 4, !dbg !15
17 | ret i32 %1, !dbg !16
18 | }
19 |
20 | declare i32 @sum(i32, i32) #1
21 |
22 | attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
23 | attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
24 |
25 | !llvm.dbg.cu = !{!0}
26 | !llvm.module.flags = !{!6, !7, !8}
27 | !llvm.ident = !{!9}
28 |
29 | !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)", isOptimized: false, runtimeVersion: 0, emissionKind: 2, enums: !2, subprograms: !3)
30 | !1 = !DIFile(filename: "main.c", directory: "/Users/alexdenisov/Projects/LLVM/Mutang/laboratory")
31 | !2 = !{}
32 | !3 = !{!4}
33 | !4 = distinct !DISubprogram(name: "test_main", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: false, variables: !2)
34 | !5 = !DISubroutineType(types: !2)
35 | !6 = !{i32 2, !"Dwarf Version", i32 2}
36 | !7 = !{i32 2, !"Debug Info Version", i32 3}
37 | !8 = !{i32 1, !"PIC Level", i32 2}
38 | !9 = !{!"clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)"}
39 | !10 = !DILocation(line: 4, column: 16, scope: !4)
40 | !11 = !DILocation(line: 4, column: 7, scope: !4)
41 | !12 = !DILocation(line: 5, column: 24, scope: !4)
42 | !13 = !DILocation(line: 5, column: 31, scope: !4)
43 | !14 = !DILocation(line: 5, column: 7, scope: !4)
44 | !15 = !DILocation(line: 7, column: 10, scope: !4)
45 | !16 = !DILocation(line: 7, column: 3, scope: !4)
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LLVM-based Mutation Testing System. Proof of Concept
2 |
3 | This is just a proof of concept. It is not intended to be runnable on your machine since it uses 'slightly forked' LLVM.
4 |
5 | You can find out more here: http://lowlevelbits.org/llvm-based-mutation-testing-system/
6 |
7 | ### High level input
8 |
9 | ```c
10 | // main.c
11 | extern int sum(int a, int b);
12 |
13 | int test_main() {
14 | int result = sum(3, 5);
15 | int result_matches = result == 8;
16 |
17 | return result_matches;
18 | }
19 | ```
20 |
21 | ```c
22 | // sum.c
23 | int someUnusedFucntion() {
24 | return 42.f;
25 | }
26 |
27 | int sum(int a, int b) {
28 | return a + b;
29 | }
30 | ```
31 |
32 | ### Low level input
33 |
34 | ```ll
35 | ; ModuleID = 'main.c'
36 | target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
37 | target triple = "x86_64-apple-macosx10.11.0"
38 |
39 | ; Function Attrs: nounwind ssp uwtable
40 | define i32 @test_main() #0 !dbg !4 {
41 | entry:
42 | %result = alloca i32, align 4
43 | %result_matches = alloca i32, align 4
44 | %call = call i32 @sum(i32 3, i32 5), !dbg !10
45 | store i32 %call, i32* %result, align 4, !dbg !11
46 | %0 = load i32, i32* %result, align 4, !dbg !12
47 | %cmp = icmp eq i32 %0, 8, !dbg !13
48 | %conv = zext i1 %cmp to i32, !dbg !13
49 | store i32 %conv, i32* %result_matches, align 4, !dbg !14
50 | %1 = load i32, i32* %result_matches, align 4, !dbg !15
51 | ret i32 %1, !dbg !16
52 | }
53 |
54 | declare i32 @sum(i32, i32) #1
55 |
56 | attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
57 | attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
58 |
59 | !llvm.dbg.cu = !{!0}
60 | !llvm.module.flags = !{!6, !7, !8}
61 | !llvm.ident = !{!9}
62 |
63 | !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)", isOptimized: false, runtimeVersion: 0, emissionKind: 2, enums: !2, subprograms: !3)
64 | !1 = !DIFile(filename: "main.c", directory: "/Users/alexdenisov/Projects/LLVM/Mutang/laboratory")
65 | !2 = !{}
66 | !3 = !{!4}
67 | !4 = distinct !DISubprogram(name: "test_main", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: false, variables: !2)
68 | !5 = !DISubroutineType(types: !2)
69 | !6 = !{i32 2, !"Dwarf Version", i32 2}
70 | !7 = !{i32 2, !"Debug Info Version", i32 3}
71 | !8 = !{i32 1, !"PIC Level", i32 2}
72 | !9 = !{!"clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)"}
73 | !10 = !DILocation(line: 4, column: 16, scope: !4)
74 | !11 = !DILocation(line: 4, column: 7, scope: !4)
75 | !12 = !DILocation(line: 5, column: 24, scope: !4)
76 | !13 = !DILocation(line: 5, column: 31, scope: !4)
77 | !14 = !DILocation(line: 5, column: 7, scope: !4)
78 | ```
79 |
80 | ```ll
81 | ; ModuleID = 'sum.c'
82 | target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
83 | target triple = "x86_64-apple-macosx10.11.0"
84 |
85 | ; Function Attrs: nounwind ssp uwtable
86 | define i32 @someUnusedFucntion() #0 !dbg !4 {
87 | entry:
88 | ret i32 42, !dbg !11
89 | }
90 |
91 | ; Function Attrs: nounwind ssp uwtable
92 | define i32 @sum(i32 %a, i32 %b) #0 !dbg !6 {
93 | entry:
94 | %a.addr = alloca i32, align 4
95 | %b.addr = alloca i32, align 4
96 | store i32 %a, i32* %a.addr, align 4
97 | store i32 %b, i32* %b.addr, align 4
98 | %0 = load i32, i32* %a.addr, align 4, !dbg !12
99 | %1 = load i32, i32* %b.addr, align 4, !dbg !13
100 | %add = add nsw i32 %0, %1, !dbg !14
101 | ret i32 %add, !dbg !15
102 | }
103 |
104 | attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
105 |
106 | !llvm.dbg.cu = !{!0}
107 | !llvm.module.flags = !{!7, !8, !9}
108 | !llvm.ident = !{!10}
109 |
110 | !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)", isOptimized: false, runtimeVersion: 0, emissionKind: 2, enums: !2, subprograms: !3)
111 | !1 = !DIFile(filename: "sum.c", directory: "/Users/alexdenisov/Projects/LLVM/Mutang/laboratory")
112 | !2 = !{}
113 | !3 = !{!4, !6}
114 | !4 = distinct !DISubprogram(name: "someUnusedFucntion", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, variables: !2)
115 | !5 = !DISubroutineType(types: !2)
116 | !6 = distinct !DISubprogram(name: "sum", scope: !1, file: !1, line: 5, type: !5, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false, variables: !2)
117 | !7 = !{i32 2, !"Dwarf Version", i32 2}
118 | !8 = !{i32 2, !"Debug Info Version", i32 3}
119 | !9 = !{i32 1, !"PIC Level", i32 2}
120 | !10 = !{!"clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)"}
121 | !11 = !DILocation(line: 2, column: 3, scope: !4)
122 | !12 = !DILocation(line: 6, column: 10, scope: !6)
123 | !13 = !DILocation(line: 6, column: 14, scope: !6)
124 | !14 = !DILocation(line: 6, column: 12, scope: !6)
125 | !15 = !DILocation(line: 6, column: 3, scope: !6)
126 | ```
127 |
128 | ### System Output
129 |
130 | ```txt
131 | --- a/sum.c
132 | --- b/sum.c
133 | @@ -3,6 +3,6 @@ int someUnusedFucntion() {
134 | }
135 |
136 | int sum(int a, int b) {
137 | - return a + b;
138 | + return a - b;
139 | }
140 |
141 | mutant killed
142 | ```
143 |
--------------------------------------------------------------------------------
/Mutang.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 4642D8DC1CAB072400F1FFF2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4642D8DB1CAB072400F1FFF2 /* main.m */; };
11 | /* End PBXBuildFile section */
12 |
13 | /* Begin PBXCopyFilesBuildPhase section */
14 | 4642D8D61CAB072400F1FFF2 /* CopyFiles */ = {
15 | isa = PBXCopyFilesBuildPhase;
16 | buildActionMask = 2147483647;
17 | dstPath = /usr/share/man/man1/;
18 | dstSubfolderSpec = 0;
19 | files = (
20 | );
21 | runOnlyForDeploymentPostprocessing = 1;
22 | };
23 | /* End PBXCopyFilesBuildPhase section */
24 |
25 | /* Begin PBXFileReference section */
26 | 4642D8D81CAB072400F1FFF2 /* Mutang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Mutang; sourceTree = BUILT_PRODUCTS_DIR; };
27 | 4642D8DB1CAB072400F1FFF2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
28 | /* End PBXFileReference section */
29 |
30 | /* Begin PBXFrameworksBuildPhase section */
31 | 4642D8D51CAB072400F1FFF2 /* Frameworks */ = {
32 | isa = PBXFrameworksBuildPhase;
33 | buildActionMask = 2147483647;
34 | files = (
35 | );
36 | runOnlyForDeploymentPostprocessing = 0;
37 | };
38 | /* End PBXFrameworksBuildPhase section */
39 |
40 | /* Begin PBXGroup section */
41 | 4642D8CF1CAB072400F1FFF2 = {
42 | isa = PBXGroup;
43 | children = (
44 | 4642D8DA1CAB072400F1FFF2 /* Mutang */,
45 | 4642D8D91CAB072400F1FFF2 /* Products */,
46 | );
47 | sourceTree = "";
48 | };
49 | 4642D8D91CAB072400F1FFF2 /* Products */ = {
50 | isa = PBXGroup;
51 | children = (
52 | 4642D8D81CAB072400F1FFF2 /* Mutang */,
53 | );
54 | name = Products;
55 | sourceTree = "";
56 | };
57 | 4642D8DA1CAB072400F1FFF2 /* Mutang */ = {
58 | isa = PBXGroup;
59 | children = (
60 | 4642D8DB1CAB072400F1FFF2 /* main.m */,
61 | );
62 | path = Mutang;
63 | sourceTree = "";
64 | };
65 | /* End PBXGroup section */
66 |
67 | /* Begin PBXNativeTarget section */
68 | 4642D8D71CAB072400F1FFF2 /* Mutang */ = {
69 | isa = PBXNativeTarget;
70 | buildConfigurationList = 4642D8DF1CAB072400F1FFF2 /* Build configuration list for PBXNativeTarget "Mutang" */;
71 | buildPhases = (
72 | 4642D8D41CAB072400F1FFF2 /* Sources */,
73 | 4642D8D51CAB072400F1FFF2 /* Frameworks */,
74 | 4642D8D61CAB072400F1FFF2 /* CopyFiles */,
75 | );
76 | buildRules = (
77 | );
78 | dependencies = (
79 | );
80 | name = Mutang;
81 | productName = Mutang;
82 | productReference = 4642D8D81CAB072400F1FFF2 /* Mutang */;
83 | productType = "com.apple.product-type.tool";
84 | };
85 | /* End PBXNativeTarget section */
86 |
87 | /* Begin PBXProject section */
88 | 4642D8D01CAB072400F1FFF2 /* Project object */ = {
89 | isa = PBXProject;
90 | attributes = {
91 | LastUpgradeCheck = 0730;
92 | ORGANIZATIONNAME = lowlevelbits;
93 | TargetAttributes = {
94 | 4642D8D71CAB072400F1FFF2 = {
95 | CreatedOnToolsVersion = 7.3;
96 | };
97 | };
98 | };
99 | buildConfigurationList = 4642D8D31CAB072400F1FFF2 /* Build configuration list for PBXProject "Mutang" */;
100 | compatibilityVersion = "Xcode 3.2";
101 | developmentRegion = English;
102 | hasScannedForEncodings = 0;
103 | knownRegions = (
104 | en,
105 | );
106 | mainGroup = 4642D8CF1CAB072400F1FFF2;
107 | productRefGroup = 4642D8D91CAB072400F1FFF2 /* Products */;
108 | projectDirPath = "";
109 | projectRoot = "";
110 | targets = (
111 | 4642D8D71CAB072400F1FFF2 /* Mutang */,
112 | );
113 | };
114 | /* End PBXProject section */
115 |
116 | /* Begin PBXSourcesBuildPhase section */
117 | 4642D8D41CAB072400F1FFF2 /* Sources */ = {
118 | isa = PBXSourcesBuildPhase;
119 | buildActionMask = 2147483647;
120 | files = (
121 | 4642D8DC1CAB072400F1FFF2 /* main.m in Sources */,
122 | );
123 | runOnlyForDeploymentPostprocessing = 0;
124 | };
125 | /* End PBXSourcesBuildPhase section */
126 |
127 | /* Begin XCBuildConfiguration section */
128 | 4642D8DD1CAB072400F1FFF2 /* Debug */ = {
129 | isa = XCBuildConfiguration;
130 | buildSettings = {
131 | ALWAYS_SEARCH_USER_PATHS = NO;
132 | CLANG_ANALYZER_NONNULL = YES;
133 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
134 | CLANG_CXX_LIBRARY = "libc++";
135 | CLANG_ENABLE_MODULES = YES;
136 | CLANG_ENABLE_OBJC_ARC = YES;
137 | CLANG_WARN_BOOL_CONVERSION = YES;
138 | CLANG_WARN_CONSTANT_CONVERSION = YES;
139 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
140 | CLANG_WARN_EMPTY_BODY = YES;
141 | CLANG_WARN_ENUM_CONVERSION = YES;
142 | CLANG_WARN_INT_CONVERSION = YES;
143 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
144 | CLANG_WARN_UNREACHABLE_CODE = YES;
145 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
146 | CODE_SIGN_IDENTITY = "-";
147 | COPY_PHASE_STRIP = NO;
148 | DEBUG_INFORMATION_FORMAT = dwarf;
149 | ENABLE_STRICT_OBJC_MSGSEND = YES;
150 | ENABLE_TESTABILITY = YES;
151 | GCC_C_LANGUAGE_STANDARD = gnu99;
152 | GCC_DYNAMIC_NO_PIC = NO;
153 | GCC_NO_COMMON_BLOCKS = YES;
154 | GCC_OPTIMIZATION_LEVEL = 0;
155 | GCC_PREPROCESSOR_DEFINITIONS = (
156 | "DEBUG=1",
157 | "$(inherited)",
158 | );
159 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
160 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
161 | GCC_WARN_UNDECLARED_SELECTOR = YES;
162 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
163 | GCC_WARN_UNUSED_FUNCTION = YES;
164 | GCC_WARN_UNUSED_VARIABLE = YES;
165 | LLVM_BUILD_DIR = /Users/alexdenisov/Projects/LLVM/build_static;
166 | LLVM_LIBS = "-lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMDebugInfoCodeView -lLLVMCodeGen -lLLVMScalarOpts -lLLVMInstCombine -lLLVMInstrumentation -lLLVMProfileData -lLLVMTransformUtils -lLLVMBitWriter -lLLVMX86Desc -lLLVMMCDisassembler -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT -lLLVMExecutionEngine -lLLVMTarget -lLLVMAnalysis -lLLVMRuntimeDyld -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMMC -lLLVMCore -lLLVMSupport -lLLVMLinker";
167 | LLVM_SOURCE_DIR = /Users/alexdenisov/Projects/LLVM/llvm;
168 | MACOSX_DEPLOYMENT_TARGET = 10.11;
169 | MTL_ENABLE_DEBUG_INFO = YES;
170 | ONLY_ACTIVE_ARCH = YES;
171 | SDKROOT = macosx;
172 | };
173 | name = Debug;
174 | };
175 | 4642D8DE1CAB072400F1FFF2 /* Release */ = {
176 | isa = XCBuildConfiguration;
177 | buildSettings = {
178 | ALWAYS_SEARCH_USER_PATHS = NO;
179 | CLANG_ANALYZER_NONNULL = YES;
180 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
181 | CLANG_CXX_LIBRARY = "libc++";
182 | CLANG_ENABLE_MODULES = YES;
183 | CLANG_ENABLE_OBJC_ARC = YES;
184 | CLANG_WARN_BOOL_CONVERSION = YES;
185 | CLANG_WARN_CONSTANT_CONVERSION = YES;
186 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
187 | CLANG_WARN_EMPTY_BODY = YES;
188 | CLANG_WARN_ENUM_CONVERSION = YES;
189 | CLANG_WARN_INT_CONVERSION = YES;
190 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
191 | CLANG_WARN_UNREACHABLE_CODE = YES;
192 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
193 | CODE_SIGN_IDENTITY = "-";
194 | COPY_PHASE_STRIP = NO;
195 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
196 | ENABLE_NS_ASSERTIONS = NO;
197 | ENABLE_STRICT_OBJC_MSGSEND = YES;
198 | GCC_C_LANGUAGE_STANDARD = gnu99;
199 | GCC_NO_COMMON_BLOCKS = YES;
200 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
201 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
202 | GCC_WARN_UNDECLARED_SELECTOR = YES;
203 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
204 | GCC_WARN_UNUSED_FUNCTION = YES;
205 | GCC_WARN_UNUSED_VARIABLE = YES;
206 | LLVM_BUILD_DIR = /Users/alexdenisov/Projects/LLVM/build_static;
207 | LLVM_LIBS = "-lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMDebugInfoCodeView -lLLVMCodeGen -lLLVMScalarOpts -lLLVMInstCombine -lLLVMInstrumentation -lLLVMProfileData -lLLVMTransformUtils -lLLVMBitWriter -lLLVMX86Desc -lLLVMMCDisassembler -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT -lLLVMExecutionEngine -lLLVMTarget -lLLVMAnalysis -lLLVMRuntimeDyld -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMMC -lLLVMCore -lLLVMSupport -lLLVMLinker";
208 | LLVM_SOURCE_DIR = /Users/alexdenisov/Projects/LLVM/llvm;
209 | MACOSX_DEPLOYMENT_TARGET = 10.11;
210 | MTL_ENABLE_DEBUG_INFO = NO;
211 | SDKROOT = macosx;
212 | };
213 | name = Release;
214 | };
215 | 4642D8E01CAB072400F1FFF2 /* Debug */ = {
216 | isa = XCBuildConfiguration;
217 | buildSettings = {
218 | GCC_PREPROCESSOR_DEFINITIONS = (
219 | __STDC_CONSTANT_MACROS,
220 | __STDC_LIMIT_MACROS,
221 | );
222 | HEADER_SEARCH_PATHS = /usr/local/include;
223 | LIBRARY_SEARCH_PATHS = (
224 | "$(LLVM_BUILD_DIR)/lib",
225 | /usr/local/lib,
226 | );
227 | OTHER_LDFLAGS = (
228 | "$(LLVM_LIBS)",
229 | "-lc++",
230 | "-lz",
231 | "-ltermcap",
232 | "-lgit2",
233 | );
234 | PRODUCT_NAME = "$(TARGET_NAME)";
235 | USER_HEADER_SEARCH_PATHS = "$(LLVM_SOURCE_DIR)/include $(LLVM_BUILD_DIR)/include";
236 | };
237 | name = Debug;
238 | };
239 | 4642D8E11CAB072400F1FFF2 /* Release */ = {
240 | isa = XCBuildConfiguration;
241 | buildSettings = {
242 | GCC_PREPROCESSOR_DEFINITIONS = (
243 | __STDC_CONSTANT_MACROS,
244 | __STDC_LIMIT_MACROS,
245 | );
246 | HEADER_SEARCH_PATHS = /usr/local/include;
247 | LIBRARY_SEARCH_PATHS = (
248 | "$(LLVM_BUILD_DIR)/lib",
249 | /usr/local/lib,
250 | );
251 | OTHER_LDFLAGS = (
252 | "$(LLVM_LIBS)",
253 | "-lc++",
254 | "-lz",
255 | "-ltermcap",
256 | "-lgit2",
257 | );
258 | PRODUCT_NAME = "$(TARGET_NAME)";
259 | USER_HEADER_SEARCH_PATHS = "$(LLVM_SOURCE_DIR)/include $(LLVM_BUILD_DIR)/include";
260 | };
261 | name = Release;
262 | };
263 | /* End XCBuildConfiguration section */
264 |
265 | /* Begin XCConfigurationList section */
266 | 4642D8D31CAB072400F1FFF2 /* Build configuration list for PBXProject "Mutang" */ = {
267 | isa = XCConfigurationList;
268 | buildConfigurations = (
269 | 4642D8DD1CAB072400F1FFF2 /* Debug */,
270 | 4642D8DE1CAB072400F1FFF2 /* Release */,
271 | );
272 | defaultConfigurationIsVisible = 0;
273 | defaultConfigurationName = Release;
274 | };
275 | 4642D8DF1CAB072400F1FFF2 /* Build configuration list for PBXNativeTarget "Mutang" */ = {
276 | isa = XCConfigurationList;
277 | buildConfigurations = (
278 | 4642D8E01CAB072400F1FFF2 /* Debug */,
279 | 4642D8E11CAB072400F1FFF2 /* Release */,
280 | );
281 | defaultConfigurationIsVisible = 0;
282 | defaultConfigurationName = Release;
283 | };
284 | /* End XCConfigurationList section */
285 | };
286 | rootObject = 4642D8D01CAB072400F1FFF2 /* Project object */;
287 | }
288 |
--------------------------------------------------------------------------------
/Mutang/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // Mutang
4 | //
5 | // Created by AlexDenisov on 29/03/16.
6 | // Copyright © 2016 lowlevelbits. All rights reserved.
7 | //
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include
16 |
17 | @import LLVM_C;
18 |
19 | LLVMModuleRef newModule(const char *path) {
20 | LLVMMemoryBufferRef buffer;
21 | char *message;
22 | if (LLVMCreateMemoryBufferWithContentsOfFile(path, &buffer, &message)) {
23 | printf("Can't create buffer: %s\n", message);
24 | exit(1);
25 | }
26 |
27 | LLVMModuleRef module;
28 | if (LLVMParseBitcode2(buffer, &module)) {
29 | printf("Can't get Bitcode\n");
30 | exit(1);
31 | }
32 |
33 | LLVMDisposeMemoryBuffer(buffer);
34 |
35 | return module;
36 | }
37 |
38 | LLVMValueRef firstTestFromModule(LLVMModuleRef module) {
39 | LLVMValueRef currentFunction = LLVMGetFirstFunction(module);
40 |
41 | while (currentFunction) {
42 | const char *name = LLVMGetValueName(currentFunction);
43 | if (LLVMIsDeclaration(currentFunction)) {
44 | // skip declarations, since we interested only in functions with body
45 | currentFunction = LLVMGetNextFunction(currentFunction);
46 | continue;
47 | }
48 |
49 | if (strncmp(name, "test", strlen("test")) == 0) {
50 | break;
51 | }
52 |
53 | currentFunction = LLVMGetNextFunction(currentFunction);
54 | }
55 |
56 | return currentFunction;
57 | }
58 |
59 | bool hasSources(const char *functionName) {
60 | if (strncmp(functionName, "llvm", strlen("llvm")) == 0) {
61 | return false;
62 | }
63 |
64 | return true;
65 | }
66 |
67 | const char *firstMutationFunctionNameForTestFunction(LLVMValueRef testFunction) {
68 | assert(LLVMIsAFunction(testFunction));
69 | assert(LLVMCountBasicBlocks(testFunction));
70 |
71 | LLVMBasicBlockRef basicBlock = LLVMGetFirstBasicBlock(testFunction);
72 |
73 | while (basicBlock) {
74 | LLVMValueRef instruction = LLVMGetFirstInstruction(basicBlock);
75 | while (instruction) {
76 | if (LLVMIsACallInst(instruction)) {
77 | assert(LLVMGetNumOperands(instruction));
78 |
79 | int functionOperand = LLVMGetNumOperands(instruction) - 1;
80 | LLVMValueRef functionDeclaration = LLVMGetOperand(instruction, functionOperand);
81 |
82 | const char *functionName = LLVMGetValueName(functionDeclaration);
83 | if (hasSources(functionName)) {
84 | return functionName;
85 | }
86 | }
87 |
88 | instruction = LLVMGetNextInstruction(instruction);
89 | }
90 |
91 | basicBlock = LLVMGetNextBasicBlock(basicBlock);
92 | }
93 |
94 | return "";
95 | }
96 |
97 | LLVMModuleRef copyOfModuleWithoutFunction(LLVMModuleRef module, const char *name) {
98 | LLVMModuleRef copyOfModule = LLVMCloneModule(module);
99 | LLVMValueRef function = LLVMGetNamedFunction(copyOfModule, name);
100 |
101 | LLVMDeleteFunction(function);
102 |
103 | return copyOfModule;
104 | }
105 |
106 | LLVMModuleRef copyOfModuleWithFunctionOnly(LLVMModuleRef module, const char *functionName) {
107 | LLVMModuleRef copyOfModule = LLVMCloneModule(module);
108 |
109 | LLVMValueRef currentFunction = LLVMGetFirstFunction(copyOfModule);
110 |
111 | while (currentFunction) {
112 | const char *name = LLVMGetValueName(currentFunction);
113 | if (LLVMIsDeclaration(currentFunction)) {
114 | // skip declarations, since we interested only in functions with body
115 | currentFunction = LLVMGetNextFunction(currentFunction);
116 | continue;
117 | }
118 |
119 | if (strcmp(name, functionName)) {
120 | LLVMValueRef functionToDelete = currentFunction;
121 | currentFunction = LLVMGetNextFunction(currentFunction);
122 | LLVMDeleteFunction(functionToDelete);
123 | continue;
124 | }
125 |
126 | currentFunction = LLVMGetNextFunction(currentFunction);
127 | }
128 |
129 | return copyOfModule;
130 | }
131 |
132 | void dumpMetadataRecursively(LLVMValueRef mdNode) {
133 | if (!mdNode) {
134 | return;
135 | }
136 |
137 | // LLVMDumpValue(mdNode);
138 |
139 | if (DILocationKind == LLVMGetMetadataKind(mdNode)) {
140 | printf("%s/%s:%d,%d\n", LLVMGetDILocationDirectory(mdNode), LLVMGetDILocationFilename(mdNode), LLVMGetDILocationLineNumber(mdNode), LLVMGetDILocationColumn(mdNode));
141 | }
142 |
143 |
144 | if (LLVMIsAMDString(mdNode)) {
145 | // unsigned int size = 0;
146 | // const char *s = LLVMGetMDString(mdNode, &size);
147 | // printf("%d %s\n", LLVMGetMetadataKind(mdNode), s);
148 | return;
149 | }
150 |
151 | unsigned int numDebugOperands = LLVMGetMDNodeNumOperands(mdNode);
152 | if (numDebugOperands) {
153 | LLVMValueRef *debugOperands = calloc(numDebugOperands, sizeof(LLVMValueRef));
154 | LLVMGetMDNodeOperands(mdNode, debugOperands);
155 |
156 | for (int i = 0; i < numDebugOperands; i++) {
157 | dumpMetadataRecursively(debugOperands[i]);
158 | }
159 |
160 | free(debugOperands);
161 | }
162 | }
163 |
164 | struct MutationPoint {
165 | LLVMValueRef function;
166 | LLVMBasicBlockRef basicBlock;
167 | LLVMValueRef instruction;
168 | };
169 |
170 | struct MutationPoint mutationPointForMutationFromFunction(LLVMValueRef function) {
171 | LLVMBasicBlockRef basicBlock = LLVMGetFirstBasicBlock(function);
172 | LLVMValueRef instruction = NULL;
173 |
174 | while (basicBlock) {
175 | instruction = LLVMGetFirstInstruction(basicBlock);
176 | while (instruction) {
177 | if (LLVMIsABinaryOperator(instruction)) {
178 | break;
179 | }
180 |
181 | instruction = LLVMGetNextInstruction(instruction);
182 | }
183 |
184 | if (instruction) {
185 | break;
186 | }
187 |
188 | basicBlock = LLVMGetNextBasicBlock(basicBlock);
189 | }
190 |
191 | struct MutationPoint mutationPoint = { .function = function, .basicBlock = basicBlock, .instruction = instruction };
192 |
193 | return mutationPoint;
194 | }
195 |
196 | struct MutationPoint makeMutationAtMutationPoint(struct MutationPoint mutationPoint) {
197 | LLVMValueRef function = mutationPoint.function;
198 | LLVMBasicBlockRef basicBlock = mutationPoint.basicBlock;
199 | LLVMValueRef instruction = mutationPoint.instruction;
200 |
201 | LLVMBuilderRef builder = LLVMCreateBuilder();
202 | LLVMPositionBuilder(builder, basicBlock, instruction);
203 |
204 | LLVMValueRef mutant = LLVMBuildNSWSub(builder, LLVMGetOperand(instruction, 0), LLVMGetOperand(instruction, 1), LLVMGetValueName(instruction));
205 |
206 | LLVMReplaceAllUsesWith(instruction, mutant);
207 | LLVMInstructionEraseFromParent(instruction);
208 |
209 | struct MutationPoint mutatedPoint = { .function = function, .basicBlock = basicBlock, .instruction = mutant };
210 |
211 | return mutatedPoint;
212 | }
213 |
214 | unsigned long long runFunction(LLVMValueRef function, LLVMModuleRef modules[], int modulesSize, LLVMModuleRef extraModule) {
215 | LLVMModuleRef firstModule = modules[0];
216 |
217 | char *error = NULL;
218 | LLVMExecutionEngineRef executionEngine;
219 | if (LLVMCreateExecutionEngineForModule(&executionEngine, firstModule, &error) != 0 ) {
220 | printf("Can't initialize engine: %s\n", error);
221 | // TODO: cleanup all allocated memory ;)
222 | exit(1);
223 | }
224 |
225 | for (int i = 1; i < modulesSize; i++) {
226 | LLVMAddModule(executionEngine, modules[i]);
227 | }
228 |
229 | LLVMAddModule(executionEngine, extraModule);
230 |
231 | LLVMGenericValueRef value = LLVMRunFunction(executionEngine, function, 0, NULL);
232 | unsigned long long result = LLVMGenericValueToInt(value, 0);
233 |
234 | LLVMModuleRef _dummy;
235 |
236 | LLVMRemoveModule(executionEngine, extraModule, &_dummy, NULL);
237 |
238 | return result;
239 | }
240 |
241 | char *sourceForModule(LLVMModuleRef module) {
242 | const char *directory = LLVMGetModuleDirectory(module);
243 | const char *filename = LLVMGetModuleFilename(module);
244 |
245 | char fullname[100];
246 | strcpy(fullname, directory);
247 | strcat(fullname, "/");
248 | strcat(fullname, filename);
249 |
250 | FILE *sourceFile = fopen(fullname, "rb");
251 | if (!sourceFile) {
252 | printf("can't open file %s: %s\n", fullname, strerror(errno));
253 | return NULL;
254 | }
255 |
256 | fseek(sourceFile, 0, SEEK_END);
257 | long size = ftell(sourceFile);
258 | fseek(sourceFile, 0, SEEK_SET);
259 |
260 | char *source = calloc(size, sizeof(char));
261 | fread(source, sizeof(char), size, sourceFile);
262 |
263 | fclose(sourceFile);
264 |
265 | return source;
266 | }
267 |
268 | char *highlevelMutantRepresentation(const char *originalSource, struct MutationPoint mutationPoint) {
269 | assert(LLVMHasMetadata(mutationPoint.instruction));
270 |
271 | LLVMValueRef metadata = LLVMGetMetadata(mutationPoint.instruction, 0);
272 |
273 | const unsigned int line = LLVMGetDILocationLineNumber(metadata);
274 | const unsigned int column = LLVMGetDILocationColumn(metadata);
275 |
276 | char *mutationSource = calloc(strlen(originalSource), sizeof(char));
277 | strcpy(mutationSource, originalSource);
278 |
279 | unsigned int currentLine = 1;
280 |
281 | char *curChar = mutationSource;
282 | while ( (*(curChar++) != '\0') ) {
283 | if (currentLine == line) {
284 | *(curChar + column - 1) = '-';
285 | break;
286 | }
287 |
288 | if (*curChar == '\n') {
289 | currentLine++;
290 | }
291 | }
292 |
293 | return mutationSource;
294 | }
295 |
296 | int mutang_diff_callback(const git_diff_delta *delta,
297 | const git_diff_hunk *hunk,
298 | const git_diff_line *line,
299 | void *payload) {
300 | FILE *fp = payload ? payload : stdout;
301 |
302 | if (line->origin == GIT_DIFF_LINE_FILE_HDR) {
303 | fwrite("--- ", 1, strlen("--- "), fp);
304 | fwrite("a/", 1, strlen("a/"), fp);
305 | fwrite(delta->old_file.path, 1, strlen(delta->old_file.path), fp);
306 | fwrite("\n", 1, strlen("\n"), fp);
307 |
308 | fwrite("--- ", 1, strlen("--- "), fp);
309 | fwrite("b/", 1, strlen("b/"), fp);
310 | fwrite(delta->new_file.path, 1, strlen(delta->new_file.path), fp);
311 | fwrite("\n", 1, strlen("\n"), fp);
312 | return 0;
313 | }
314 |
315 | if (line->origin == GIT_DIFF_LINE_HUNK_HDR) {
316 | fwrite(line->content, 1, line->content_len, fp);
317 | return 0;
318 | }
319 |
320 | if (line->origin != GIT_DIFF_LINE_CONTEXT &&
321 | line->origin != GIT_DIFF_LINE_ADDITION &&
322 | line->origin != GIT_DIFF_LINE_DELETION) {
323 | return 0;
324 | }
325 |
326 | fputc(line->origin, fp);
327 | fwrite(line->content, 1, line->content_len, fp);
328 | return 0;
329 | }
330 |
331 | int main(int argc, const char * argv[]) {
332 | assert(argc == 2);
333 |
334 | char moduleWithTestPath[100];
335 | char moduleWithTesteePath[100];
336 |
337 | const char *laboratoryPath = argv[1];
338 |
339 | strcpy(moduleWithTestPath, laboratoryPath);
340 | strcpy(moduleWithTesteePath, laboratoryPath);
341 |
342 | strcat(moduleWithTestPath, "/main.bc");
343 | strcat(moduleWithTesteePath, "/sum.bc");
344 |
345 | const LLVMModuleRef moduleWithTest = newModule(moduleWithTestPath);
346 | const LLVMModuleRef moduleWithTestee = newModule(moduleWithTesteePath);
347 |
348 | LLVMValueRef testFunction = firstTestFromModule(moduleWithTest);
349 | const char *mutationFunctionName = firstMutationFunctionNameForTestFunction(testFunction);
350 |
351 | LLVMModuleRef testeeModuleWithoutTestee = copyOfModuleWithoutFunction(moduleWithTestee, mutationFunctionName);
352 |
353 | LLVMModuleRef moduleWithMutation = copyOfModuleWithFunctionOnly(moduleWithTestee, mutationFunctionName);
354 |
355 | LLVMValueRef functionForMutation = LLVMGetNamedFunction(moduleWithMutation, mutationFunctionName);
356 |
357 | struct MutationPoint mutationPoint = mutationPointForMutationFromFunction(functionForMutation);
358 | __unused struct MutationPoint mutatedPoint = makeMutationAtMutationPoint(mutationPoint);
359 |
360 | char *originalSource = sourceForModule(moduleWithMutation);
361 | char *mutantSource = highlevelMutantRepresentation(originalSource, mutationPoint);
362 |
363 | git_libgit2_init();
364 |
365 | git_patch *patch;
366 |
367 | git_patch_from_buffers(&patch,
368 | originalSource, strlen(originalSource), LLVMGetModuleFilename(moduleWithMutation),
369 | mutantSource, strlen(mutantSource), LLVMGetModuleFilename(moduleWithMutation),
370 | NULL);
371 |
372 | git_patch_print(patch, mutang_diff_callback, NULL);
373 |
374 | git_patch_free(patch);
375 |
376 | git_libgit2_shutdown();
377 |
378 | free(originalSource);
379 | free(mutantSource);
380 |
381 | LLVMLinkInMCJIT();
382 | LLVMInitializeNativeTarget();
383 | LLVMInitializeNativeAsmPrinter();
384 |
385 | LLVMModuleRef modules[] = { moduleWithTest, testeeModuleWithoutTestee };
386 |
387 | unsigned long long initialResult = runFunction(testFunction, modules, 2, moduleWithTestee);
388 | unsigned long long mutatedResult = runFunction(testFunction, modules, 2, moduleWithMutation);
389 |
390 | if (initialResult != mutatedResult) {
391 | printf("mutant killed\n");
392 | } else {
393 | printf("mutant survived\n");
394 | }
395 |
396 | LLVMDisposeModule(moduleWithTest);
397 | LLVMDisposeModule(moduleWithTestee);
398 | LLVMDisposeModule(moduleWithMutation);
399 | LLVMDisposeModule(testeeModuleWithoutTestee);
400 |
401 | return 0;
402 | }
403 |
--------------------------------------------------------------------------------