<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>Comprehensive Evaluation of Cross Translation Unit Symbolic Execution∗</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Endre Fülöp</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Norbert Pataki</string-name>
          <email>patakino@elte.hu</email>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>ELTE Eötvös Loránd University, Budapest, Hungary Faculty of Informatics, 3in Research Group</institution>
          ,
          <addr-line>Martonvásár</addr-line>
          ,
          <country country="HU">Hungary</country>
        </aff>
      </contrib-group>
      <pub-date>
        <year>2020</year>
      </pub-date>
      <fpage>29</fpage>
      <lpage>31</lpage>
      <abstract>
        <p>Static analysis is a great approach to find bugs and code smells. Some of the errors span across multiple translation units (TUs). Symbolic execution is a primary static analysis technique. Symbols are used to represent unknown values (e.g. user input), and symbolic calculations are carried out on them. Clang Static Analyzer (SA) is an open-source symbolic execution engine for C/C++/Objective-C. The default behaviour of the SA does not support cross translation unit analysis, but it can be parametrized to enable analysis techniques spanning across many TUs. In this paper, we evaluate the cross translation unit symbolic execution in a comprehensive way. Diferent caching methods, diferent approaches are considered. We compare the analysis of open source projects. The aim is an optimal configuration for the tool.</p>
      </abstract>
      <kwd-group>
        <kwd>symbolic execution</kwd>
        <kwd>cross translation unit</kwd>
        <kwd>Clang</kwd>
      </kwd-group>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>1. Introduction</title>
      <p>
        Static analysis is a well-known method to detect bugs without execution of code
[
        <xref ref-type="bibr" rid="ref7">7</xref>
        ]. Static analysis works with source code, mainly focuses on bug detection [
        <xref ref-type="bibr" rid="ref3">3</xref>
        ].
However, refactoring, obfuscation and complexity metrics tools also use static
analysis. Static analysis tools build up the abstract syntax tree (AST) in order to run
a.cpp:
int f( int&amp; r )
{
}
++r;
return 100 / ( r - 15 );
int f( int&amp; r );
void g()
{
int x = 14;
f( x );
if ( x != 15 )
{
}
}
      </p>
      <p>
        int * p = new int;
AST-consumers on them, which are used to implement algorithms over syntax trees
[
        <xref ref-type="bibr" rid="ref5">5</xref>
        ].
      </p>
      <p>
        Symbolic execution is a major static analysis in which symbols are used to
represent unknown, and calculations are carried out on them [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ].
      </p>
      <p>
        Unfortunately, separate compilation makes cross translation unit analysis
challenging for C family languages. Therefore, many tools do not support cross
translation analysis [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ]. Unity build is a technique for using a single translation unit,
but creating unity builds also has many dificulties [10]. However, the scope of the
analysis has a significant impact on the precision [
        <xref ref-type="bibr" rid="ref6">6</xref>
        ].
      </p>
      <p>Let us consider the code snippets on Figure 1 that belong to two diferent
translation units:</p>
      <p>If one were to analyze the first translation unit via single-TU analysis, starting
the symbolic execution from function f, the value of the parameter could not be
reasoned about. Therefore producing a warning for the return statement, and
stating that the expression is potentially a division by zero is not in line with the
conservative policy of static analysis. The goal of the analyzer is to identify real
bugs and help the programmer fix error-prone code constructs. However, too many
bug-reports are also discouraged for practical reasons. In function g, no knowledge
about the value of x right after the function call to f. In this case, one gets warning
about the memory leak, but it is dead code; thus it is a false positive finding.</p>
      <p>C/C++ programmers have been eager for a more precise solution, therefore
we improve the Clang SA for the cross translation unit analysis, but the potential
configuration settings of the new version have not been evaluated.</p>
      <p>The rest of this paper is organized as follows. We present the approach of cross
translation unit symbolic execution in section 2. We define what are the parameters
of the improved analysis in section 3. We evaluate the analysis processes and
present results in section 4. Finally, this paper concludes in section 5.</p>
    </sec>
    <sec id="sec-2">
      <title>2. Cross Translation Unit Symbolic Execution</title>
      <p>
        Clang Static Analyzer (SA) is a powerful symbolic execution engine for the C/C++
and the Objective-C languages. Moreover, it is based on the Clang compiler
infrastructure [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ]. However, it was not able to perform cross translation unit analysis for
a long time. However, many problems span across multiple translation units. We
improved it to achieve a more sophisticated approach [
        <xref ref-type="bibr" rid="ref6">6</xref>
        ].
      </p>
      <p>The SA used a one-pass analysis initially, however, the CTU analysis needs
preprocessing on the project. Thanks to this dependency, we we had to extend
the analysis driver to support two-pass analysis. In the first phase, an index file is
created based on the compilation database and source code. This index file contains
the mapping of function definition and translation unit. The source code is parsed;
thus the AST is built. The ASTs are serialized in binary format. In the second
phase, SA analyzes all translation units. When it reaches a function call that has
no definition in the current unit, SA finds its serialized AST snippet based on the
index file. In this case, a unique merging approach is required. Both the compiled
in-memory form of the current file’s AST and the binary serialized external one
contain their distinct symbol tables and type representations. They have diferent
managers regarding the source locations as well. Loading and merging ASTs have
runtime cost; therefore we developed caching mechanisms.</p>
    </sec>
    <sec id="sec-3">
      <title>3. Evaluation</title>
      <p>The symbolic execution engine of Clang SA implements interprocedural analysis by
inlining the definition of the called function when the analysis reaches said function
call. This inlining is not always performed however, for example if the definition
is not available inside the translation unit. Single-TU analysis will disregard the
call expression, and performs some invalidation on values possibly reachable by
the function (e.g. parameters taken by reference, global variables). CTU analysis
makes the definitions from other TU-s available to the analyzer, therefore
increasing the number inlined functions, and at the same time decreasing the number
and efect of invalidations. The analysis proceeds with the consumption of the
statements of the function body as if they were lifted into the current scope. The
analysis employs thresholds to limit the execution time of the analysis.</p>
      <p>
        The configuration of the CTU symbolic execution contains some settings. These
settings afect the runtime performance and memory consumption significantly [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ].
With inlined function definitions, the analyzer has the capability of exploring a
bigger part of the project code. This does not necessarily lead to more bugs found,
but measurements seem to indicate, that a higher amount of bugs is detected when
the analysis is ran in CTU mode.
      </p>
      <p>One of the most critical parameters is the maximal number of translation units
to process when an external code snippet is required for a more sophisticated
approach. On the one hand, the increase in this parameter means more precise
analysis. On the other hand, there are limitations in the symbolic execution engine
to cancel the analysis, even if the maximal number of allowed TUs is not exceeded.</p>
      <p>There are two diferent modes for loading external AST. The users can select
between the two-pass analysis and on-demand loading of external AST approaches.</p>
      <p>We provide caching mechanisms, as well. Function-wise and translation
unitwise mechanisms are supported. If an external code snippet is required,
functionwise solution means that only the AST of the called function is cached. The
translation-unit-wise approach provides the caching the AST of the entire
translation unit, not just part that belongs to the called function.</p>
      <p>We tested the CTU symbolic execution with respect to the following projects:
• Tmux1, an open-source project written in C
• Xerces2, an open-source project written in C++</p>
      <sec id="sec-3-1">
        <title>The following metrics were collected: •</title>
      </sec>
      <sec id="sec-3-2">
        <title>Wall time of execution</title>
        <p>• Resident memory usage
• Disk usage of the analysis
We collect the metrics based on the following parameters:
• Method used
– non-CTU as the baseline
– AST-dump based CTU
– on-demand-parsed CTU
• TU unit threshold</p>
      </sec>
    </sec>
    <sec id="sec-4">
      <title>4. Results</title>
      <p>The measurements were run on a Intel(R) Xeon(R) CPU X5670 @2.93GHz
workstation with 24 virtual cores. Each measurement is driven by CodeChecker3, with
the help of run orchestrator CSA testbench4. The runtime metrics wall clock time,
and memory usage were taken with time tool5.</p>
      <p>The evaluation of CTU analysis methods shows a definite increase in both
analysis time and result-count in case of both simple and on-demand modes for
Tmux as seen on Table 1 and for Xerxes on Table 2. The CTU modes make
1https://github.com/tmux/tmux
2https://github.com/apache/xerces-c
3https://github.com/Ericsson/CodeChecker
4https://github.com/Xazax-hun/csa-testbench
5https://www.gnu.org/software/time
Method</p>
      <p>Threshold</p>
      <p>Bugs
Non-CTU
Dump based CTU
On-demand CTU
21
21
36
121
154
159
161
162
21
36
121
154
159
161
162
109
109
225
289
335
362
366
368
109
225
296
329
355
360
362</p>
      <p>Time</p>
      <p>(s)
662.04
779.71
1143.99
1715.64
1946.96
2073.77
2096.85
2074.01
719.13
1261.06
1975.93
2281.72
2426.03
2482.41
2489.72</p>
      <p>Time</p>
      <p>(s)
1437.24
1607.94
10858.03
17461.60
21300.30
22549.00
23630.78
23938.71
1544.32
12084.36
21402.23
25186.48
26988.73
28349.59
28790.37</p>
      <p>Tmux CTU with thresholds
the analyzer a more significant part of the project available, thus increasing the
amount of information accessible to the analyzer. The runtime cost of the diferent
analysis methods can be seen on Figure 2 and Figure 3 for Tmux and Xerces
respectively. The increase in result-count could also potentially mean that more
false positives are produced. The programmer must make the decision whether a
ifnding is positive or not on an individual basis. This means that CTU analysis
could potentially provide more results in the project at the cost of an increase in the
development time. The results also show that the nature of bugs being found varies,
as multiple domains get connected by CTU, that are separated by modularization.
For example, bugs concerning memory access are found along deeper bug paths, as
the memory handling logic is most of the time separated into diferent translation
units. CTU analysis introduces more statements to be analyzed. These statements
use the same budget as the non-imported ones. Even with the same
statementbudget value, the exact characteristics of found bugs depend on many factors,
including the path-exploration strategy employed, the position of the inlined calls,
and the structure of the inlined functions body. The CTU analysis therefore can
lead to deeper bug paths as well as shallower ones. Consider the example of a
function which uses a call very early during its execution. In the non-CTU case,
the call is ignored, and execution proceeds with statements after it. There are
some bugs found with either deep or shallow paths. Now consider the analysis of
the same function but with CTU mode enabled. The aforementioned call is now
matched with a definition from another TU, and is inlined. There is a possiblity
now that the inlined function is very complex, or maybe more functions are inlined
during the evaluation of said function. This could lead to early exhaustion of the
analysis budget, and potentially the exclusion of the latter half of the original
functions body. Totally disjoint sets of results are possible.</p>
      <p>Xerces CTU with thresholds</p>
      <p>There is also an interesting behaviour in case of analyzing projects up to their
CTU-threshold-limit. TMUX was analyzed with a TU threshold of 100 in cases
the threshold value was not explicitly mentioned. During this analysis we have
tracked the messages of the analyzer. We found that even if a maximal amount of
100 was given, there were no TUs that triggered an import of more than 47 other
TUs. This means that with default settings, the analyzer considered no more than
this amount TUs during analysis, which we call the CTU-threshold-limit. So with
thresholds ranging from 0 (which signifies equivalent behaviour as non-CTU) up to
48, the whole range of possible values were measured. Thus the threshold charts
saturation-like shape in case of bugs found.</p>
    </sec>
    <sec id="sec-5">
      <title>5. Limitations and Conclusion</title>
      <p>The disk usage of CTU analysis could prove to be a significant hindrance, as there
is a usually a magnitude of diference between the size of the results produced, and
the size of the dumped AST-nodes in case of simple CTU analysis. The on-demand
CTU analysis can mitigate this, but at the cost of parsing the source files on-the-fly.
These tradeofs should be considered before switching analysis modes.</p>
      <p>On-demand CTU analysis has further weaknesses. The produced AST is not
precisely equivalent to the dumped AST. We have identified three possible causes
of the non-equivalence. One could be that the serialization and deserialization
steps do not give back the original AST, this is still under investigation. Another
reason could be the liberal handling of language elements in case of creating
serialized AST dumps, as opposed to be more strict policy employed during on-demand
parsing. This is more likely, but the exact implementation details of narrowing the
gap is under revision. The last reason could be the liberal detection of compilation
command flags, and is deemed the least probable. Further investigation is needed,
but recent discussions suggest that an architecturally more robust and more
scalable approach could circumvent the first two reasons. In the case of medium-sized
projects, the diferences of AST are not numerous enough to produce diferent
results; however, in the case of more complex projects, even the bugs are found difer.
Currently we are verifying whether the AST serialization is to be held accountable
for this phenomenon.</p>
      <p>We found that the caching is necessary for the analysis to be successful. Clang
is relying on every part of the AST to be held inside the memory. When switching
of the caching, we found that the analysis asserted on multiple invariant properties
of the AST being violated, as the AST nodes were already destructed when the
analysis reached them.
[10] Mihalicza, J., How #includes Afect Build Times in Large Systems, in Proc. of
the 8th International Conference on Applied Informatics (ICAI 2010), Vol. 2, pp.
343–350.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          [1]
          <string-name>
            <surname>Anand</surname>
            ,
            <given-names>S.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Godefroid</surname>
            ,
            <given-names>P.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Tillman</surname>
            ,
            <given-names>N.</given-names>
          </string-name>
          ,
          <article-title>Demand-driven Compositional Symbolic Execution</article-title>
          ,
          <source>in Proc. of the Theory and Practice of Software, 14th International Conference on Tools and Algorithms for the Construction and Analysis of Systems</source>
          , pp.
          <fpage>367</fpage>
          -
          <lpage>381</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          [2]
          <string-name>
            <surname>Arroyo</surname>
            ,
            <given-names>M.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Chiotta</surname>
            <given-names>F.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Bavera</surname>
            <given-names>F.</given-names>
          </string-name>
          ,
          <article-title>An user configurable Clang Static Analyzer taint checker</article-title>
          ,
          <source>in Proc. of the 2016 35th International Conference of the Chilean Computer Science Society (SCCC)</source>
          , pp.
          <fpage>1</fpage>
          -
          <lpage>12</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          [3]
          <string-name>
            <surname>Babati</surname>
            ,
            <given-names>B.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Horváth</surname>
            ,
            <given-names>G.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Májer</surname>
            ,
            <given-names>V.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Pataki</surname>
            ,
            <given-names>N.</given-names>
          </string-name>
          ,
          <article-title>Static Analysis Toolset with Clang</article-title>
          ,
          <source>in Proc. of the 10th International Conference on Applied Informatics (ICAI</source>
          <year>2017</year>
          ), pp.
          <fpage>23</fpage>
          -
          <lpage>29</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          [4]
          <string-name>
            <surname>Baldoni</surname>
            ,
            <given-names>R.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Coppa</surname>
            ,
            <given-names>E.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Cono</surname>
            <given-names>D</given-names>
          </string-name>
          'elia,
          <string-name>
            <given-names>D.</given-names>
            ,
            <surname>Demetrescu</surname>
          </string-name>
          ,
          <string-name>
            <given-names>C.</given-names>
            ,
            <surname>Finocchi</surname>
          </string-name>
          ,
          <string-name>
            <surname>I.</surname>
          </string-name>
          ,
          <article-title>A Survey of Symbolic Execution Techniques, ACM Computing Surveys</article-title>
          , Vol.
          <volume>51</volume>
          (
          <issue>3</issue>
          ) (
          <year>2018</year>
          ), Article No.:
          <volume>50</volume>
          .
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          [5]
          <string-name>
            <surname>Emanuelsson</surname>
            ,
            <given-names>P.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Nilsson</surname>
            <given-names>U.</given-names>
          </string-name>
          ,
          <source>A Comparative Study of Industrial Static Analysis Tools, Electronic notes in theoretical computer science</source>
          , Vol.
          <volume>217</volume>
          (
          <year>2008</year>
          ), pp.
          <fpage>5</fpage>
          -
          <lpage>21</lpage>
          ,
          <year>2008</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          [6]
          <string-name>
            <surname>Horváth</surname>
            ,
            <given-names>G.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Szécsi</surname>
            ,
            <given-names>P.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Gera</surname>
            ,
            <given-names>Z.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Krupp</surname>
            ,
            <given-names>D.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Pataki</surname>
            ,
            <given-names>N.</given-names>
          </string-name>
          ,
          <article-title>Challenges of Implementing Cross Translation Unit Analysis in Clang Static Analyzer</article-title>
          ,
          <source>in Proc. of 2018 IEEE 18th International Working Conference on Source Code Analysis and Manipulation (SCAM</source>
          <year>2018</year>
          ), pp.
          <fpage>171</fpage>
          -
          <lpage>176</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          [7]
          <string-name>
            <surname>Johnson</surname>
            ,
            <given-names>B.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Song</surname>
            ,
            <given-names>Y.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Murphy-Hill</surname>
            ,
            <given-names>E.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Bowdidge</surname>
            ,
            <given-names>R.</given-names>
          </string-name>
          ,
          <article-title>Why don't software developers use static analysis tools to find bugs?</article-title>
          <source>in Proc. of the 2013 International Conference on Software Engineering</source>
          , ICSE '
          <fpage>13</fpage>
          . (
          <year>2013</year>
          ), pp.
          <fpage>672</fpage>
          -
          <lpage>681</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          [8]
          <string-name>
            <surname>Joshi</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Tewari</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Kumar</surname>
            ,
            <given-names>V.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Bordoloi</surname>
            ,
            <given-names>D.</given-names>
          </string-name>
          ,
          <article-title>Integrating static analysis tools for improving operating system security</article-title>
          ,
          <source>International Journal of Computer Science and Mobile Computing</source>
          , Vol.
          <volume>3</volume>
          (
          <issue>4</issue>
          ) (
          <year>2014</year>
          ), pp.
          <fpage>1251</fpage>
          -
          <lpage>1258</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          [9]
          <string-name>
            <surname>King</surname>
            ,
            <given-names>C.</given-names>
          </string-name>
          ,
          <article-title>Symbolic execution and program testing</article-title>
          ,
          <source>Communications of the ACM</source>
          Vol.
          <volume>19</volume>
          (
          <year>1976</year>
          ), pp.
          <fpage>385</fpage>
          -
          <lpage>394</lpage>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>