-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathCompilation.qll
More file actions
137 lines (118 loc) · 4.29 KB
/
Compilation.qll
File metadata and controls
137 lines (118 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
* Provides a class representing individual compiler invocations that occurred during the build.
*/
import semmle.code.cpp.File
/*
* These two helper predicates are used to associate a unique integer with
* each `@compilation`, for use in the `toString` method of `Compilation`.
* These integers are not stable across trap imports, but stable across
* runs with the same database.
*/
private predicate id(@compilation x, @compilation y) { x = y }
private predicate idOf(@compilation x, int y) = equivalenceRelation(id/2)(x, y)
/**
* An invocation of the compiler. Note that more than one file may be
* compiled per invocation. For example, this command compiles three
* source files:
*
* gcc -c f1.c f2.c f3.c
*
* Three things happen to each file during a compilation:
*
* 1. The file is compiled by a real compiler, such as gcc or VC.
* 2. The file is parsed by the CodeQL C++ front-end.
* 3. The parsed representation is converted to database tables by
* the CodeQL extractor.
*
* This class provides CPU and elapsed time information for steps 2 and 3,
* but not for step 1.
*/
class Compilation extends @compilation {
/** Gets a textual representation of this element. */
string toString() {
exists(int i |
idOf(this, i) and
result = "<compilation #" + i.toString() + ">"
)
}
/** Gets a file compiled during this invocation. */
File getAFileCompiled() { result = this.getFileCompiled(_) }
/** Gets the `i`th file compiled during this invocation */
File getFileCompiled(int i) { compilation_compiling_files(this, i, unresolveElement(result)) }
/**
* Gets the amount of CPU time spent processing file number `i` in the C++
* front-end.
*/
float getFrontendCpuSeconds(int i) { compilation_time(this, i, 1, result) }
/**
* Gets the amount of elapsed time while processing file number `i` in the
* C++ front-end.
*/
float getFrontendElapsedSeconds(int i) { compilation_time(this, i, 2, result) }
/**
* Gets the amount of CPU time spent processing file number `i` in the
* extractor.
*/
float getExtractorCpuSeconds(int i) { compilation_time(this, i, 3, result) }
/**
* Gets the amount of elapsed time while processing file number `i` in the
* extractor.
*/
float getExtractorElapsedSeconds(int i) { compilation_time(this, i, 4, result) }
/**
* Gets an argument passed to the extractor on this invocation.
*/
string getAnArgument() { result = this.getArgument(_) }
/**
* Gets the `i`th argument passed to the extractor on this invocation.
*
* If the compiler was invoked as `gcc -c f1.c f2.c f3.c` then this
* will typically hold for
*
* i | result
* - | ---
* 0 | *path to extractor*
* 1 | `--mimic`
* 2 | `/usr/bin/gcc`
* 3 | `-c`
* 4 | f1.c
* 5 | f2.c
* 6 | f3.c
*/
string getArgument(int i) { compilation_args(this, i, result) }
/**
* Gets an expanded argument passed to the extractor on this invocation.
*/
string getAnExpandedArgument() { result = this.getExpandedArgument(_) }
/**
* Gets the `i`th expanded argument passed to the extractor on this
* invocation.
*
* This is similar to `getArgument`, but for a `@someFile` argument, it
* includes the arguments from that file, rather than just taking the
* argument literally.
*/
string getExpandedArgument(int i) {
if exists(string arg | compilation_expanded_args(this, _, arg))
then compilation_expanded_args(this, i, result)
else result = this.getArgument(i)
}
/**
* Gets the total amount of CPU time spent processing all the files in the
* front-end and extractor.
*/
float getTotalCpuSeconds() { compilation_finished(this, result, _) }
/**
* Gets the total amount of elapsed time while processing all the files in
* the front-end and extractor.
*/
float getTotalElapsedSeconds() { compilation_finished(this, _, result) }
/**
* Holds if the extractor terminated normally. Terminating with an exit
* code indicating that an error occurred is considered normal
* termination, but crashing due to something like a segfault is not.
*/
predicate normalTermination() { compilation_finished(this, _, _) }
/** Holds if this compilation was compiled using the "none" build mode. */
predicate buildModeNone() { compilation_build_mode(this, 0) }
}