Skip to content

Commit 1d9c3b3

Browse files
committed
Python: call-graph tracing: callable => callee
to use consistent naming
1 parent 3127bb2 commit 1d9c3b3

File tree

6 files changed

+35
-36
lines changed

6 files changed

+35
-36
lines changed

python/tools/recorded-call-graph-metrics/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
also known as _call graph tracing_.
44

5-
Execute a python program and for each call being made, record the call and callable. This allows us to compare call graph resolution from static analysis with actual data -- that is, can we statically determine the target of each actual call correctly.
5+
Execute a python program and for each call being made, record the call and callee. This allows us to compare call graph resolution from static analysis with actual data -- that is, can we statically determine the target of each actual call correctly.
66

77
This is still in the early stages, and currently only supports a very minimal working example (to show that this approach might work).
88

python/tools/recorded-call-graph-metrics/cg_trace.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
"""Call Graph tracing.
44
5-
Execute a python program and for each call being made, record the call and callable. This
5+
Execute a python program and for each call being made, record the call and callee. This
66
allows us to compare call graph resolution from static analysis with actual data -- that
77
is, can we statically determine the target of each actual call correctly.
88
@@ -37,7 +37,7 @@
3737

3838
@dataclasses.dataclass(frozen=True)
3939
class Call():
40-
"""A call to a callable
40+
"""A call
4141
"""
4242
filename: str
4343
linenum: int
@@ -59,12 +59,11 @@ def from_frame(cls, frame, debugger: bdb.Bdb):
5959

6060

6161
@dataclasses.dataclass(frozen=True)
62-
class Callable():
63-
"""A callable (Function/Lambda) should (hopefully) be uniquely identified by its name and
64-
location (filename+line number)
62+
class Callee():
63+
"""A callee (Function/Lambda/???)
6564
66-
TODO: Callable is maybe not a good name, since classes with __call__ will return true
67-
for the python code `callable(cls)` -- will have to consider how __call__ is handled
65+
should (hopefully) be uniquely identified by its name and location (filename+line
66+
number)
6867
"""
6968
funcname: str
7069
filename: str
@@ -97,10 +96,10 @@ def __init__(self):
9796

9897
def user_call(self, frame, argument_list):
9998
call = Call.from_frame(frame.f_back, self)
100-
callable = Callable.from_frame(frame, self)
99+
callee = Callee.from_frame(frame, self)
101100

102-
# _print(f'{call} -> {callable}')
103-
self.recorded_calls.add((call, callable))
101+
# _print(f'{call} -> {callee}')
102+
self.recorded_calls.add((call, callee))
104103

105104

106105
################################################################################
@@ -127,10 +126,10 @@ class CSVExporter(Exporter):
127126
def export(recorded_calls, outfile_path):
128127
with open(outfile_path, 'w', newline='') as csv_file:
129128
writer = None
130-
for (call, callable) in recorded_calls:
129+
for (call, callee) in recorded_calls:
131130
data = {
132131
**Exporter.dataclass_to_dict(call),
133-
**Exporter.dataclass_to_dict(callable)
132+
**Exporter.dataclass_to_dict(callee)
134133
}
135134

136135
if writer is None:
@@ -152,10 +151,10 @@ def export(recorded_calls, outfile_path):
152151

153152
root = ET.Element('root')
154153

155-
for (call, callable) in recorded_calls:
154+
for (call, callee) in recorded_calls:
156155
data = {
157156
**Exporter.dataclass_to_dict(call),
158-
**Exporter.dataclass_to_dict(callable)
157+
**Exporter.dataclass_to_dict(callee)
159158
}
160159

161160
rc = ET.SubElement(root, 'recorded_call')
@@ -216,8 +215,8 @@ def export(recorded_calls, outfile_path):
216215
elif opts.xml:
217216
XMLExporter.export(cgt.recorded_calls, opts.xml)
218217
else:
219-
for (call, callable) in cgt.recorded_calls:
220-
print(f'{call} -> {callable}')
218+
for (call, callee) in cgt.recorded_calls:
219+
print(f'{call} -> {callee}')
221220

222221
print('--- captured stdout ---')
223222
print(captured_stdout.getvalue(), end='')
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<root>
2-
<recorded_call call_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" call_linenum="10" call_inst_index="36" callable_funcname="bar" callable_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" callable_linenum="4" />
3-
<recorded_call call_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" call_linenum="7" call_inst_index="18" callable_funcname="foo" callable_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" callable_linenum="1" />
4-
<recorded_call call_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" call_linenum="10" call_inst_index="30" callable_funcname="foo" callable_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" callable_linenum="1" />
5-
<recorded_call call_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" call_linenum="8" call_inst_index="24" callable_funcname="bar" callable_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" callable_linenum="4" />
2+
<recorded_call call_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" call_linenum="7" call_inst_index="18" callee_funcname="foo" callee_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" callee_linenum="1" />
3+
<recorded_call call_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" call_linenum="8" call_inst_index="24" callee_funcname="bar" callee_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" callee_linenum="4" />
4+
<recorded_call call_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" call_linenum="10" call_inst_index="30" callee_funcname="foo" callee_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" callee_linenum="1" />
5+
<recorded_call call_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" call_linenum="10" call_inst_index="36" callee_funcname="bar" callee_filename="/home/rasmus/code/ql/python/tools/recorded-call-graph-metrics/example/simple.py" callee_linenum="4" />
66
</root>
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import RecordedCalls
22

3-
from ValidRecordedCall rc, Call call, Function callable, CallableValue callableValue
3+
from ValidRecordedCall rc, Call call, Function callee, CallableValue calleeValue
44
where
55
call = rc.getCall() and
6-
callable = rc.getCallable() and
7-
callableValue.getScope() = callable and
8-
callableValue.getACall() = call.getAFlowNode()
9-
select call, "-->", callable
6+
callee = rc.getCallee() and
7+
calleeValue.getScope() = callee and
8+
calleeValue.getACall() = call.getAFlowNode()
9+
select call, "-->", callee

python/tools/recorded-call-graph-metrics/ql/RecordedCalls.qll

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,23 @@ class RecordedCall extends XMLElement {
1616
result.getLocation().hasLocationInfo(this.call_filename(), this.call_linenum(), _, _, _)
1717
}
1818

19-
string callable_filename() { result = this.getAttributeValue("callable_filename") }
19+
string callee_filename() { result = this.getAttributeValue("callee_filename") }
2020

21-
int callable_linenum() { result = this.getAttributeValue("callable_linenum").toInt() }
21+
int callee_linenum() { result = this.getAttributeValue("callee_linenum").toInt() }
2222

23-
string callable_funcname() { result = this.getAttributeValue("callable_funcname") }
23+
string callee_funcname() { result = this.getAttributeValue("callee_funcname") }
2424

25-
Function getCallable() {
26-
result.getLocation().hasLocationInfo(this.callable_filename(), this.callable_linenum(), _, _, _)
25+
Function getCallee() {
26+
result.getLocation().hasLocationInfo(this.callee_filename(), this.callee_linenum(), _, _, _)
2727
}
2828
}
2929

3030
/**
31-
* Class of recorded calls where we can uniquely identify both the `call` and the `callable`.
31+
* Class of recorded calls where we can uniquely identify both the `call` and the `callee`.
3232
*/
3333
class ValidRecordedCall extends RecordedCall {
3434
ValidRecordedCall() {
3535
strictcount(this.getCall()) = 1 and
36-
strictcount(this.getCallable()) = 1
36+
strictcount(this.getCallee()) = 1
3737
}
3838
}

python/tools/recorded-call-graph-metrics/ql/UnidentifiedRecordedCalls.ql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ import RecordedCalls
22

33
from RecordedCall rc
44
where not rc instanceof ValidRecordedCall
5-
select "Could not uniquely identify this recorded call (either call or callable was not uniquely identified)",
6-
rc.call_filename(), rc.call_linenum(), rc.call_inst_index(), "-->", rc.callable_filename(),
7-
rc.callable_linenum(), rc.callable_funcname()
5+
select "Could not uniquely identify this recorded call (either call or callee was not uniquely identified)",
6+
rc.call_filename(), rc.call_linenum(), rc.call_inst_index(), "-->", rc.callee_filename(),
7+
rc.callee_linenum(), rc.callee_funcname()

0 commit comments

Comments
 (0)