electronica Nov 2014
43
D
EVELOPMENT
T
OOLS
nated. Such program transformations occur,
among other things, during optimizations,
such as for example, loop transformations,
loop splitting, loop fusions or loop expan-
sions, if-then-else transformations, such as
for example, the elimination of a statement
branch as well as conversions of basic blocks
to table accesses. The program structure (in
other words, the basic blocks), whose pro-
gram address and size as well as their relations
to other, can be determined statically and
dynamically. The debug information from the
program file can also be used, which exists, for
example, in DWARF format and, among other
things, contains the mapping of line num-
bers to program addresses and the program
addresses of the basic blocks. However the
size of the basic blocks and their relations to
other are not contained in the DWARF format.
The latter can be determined by disassembling
the machine code statements and subsequent
interpretation, emulation or simulation. How-
ever, this static code analysis is very complex
and is therefore rarely performed. The most
dynamic trace information contains the
addresses of the statements actually executed
and the sequence of execution. From this
information, a view can be generated of possi-
ble basic blocks and their view. However, only
the basic blocks actually executed are recog-
nizable. Accordingly, since in this way it is not
possible to determine which basic blocks are
not executed, a reliable coverage analysis can
therefore not be carried out.
The debugging information in the program
is usually sufficient in order to determine
the coverage of the source code lines (C0
coverage). However, in order to additionally
determine the decision coverage (C1 cover-
age) from trace data, the relations between
the basic blocks are necessary. But, as already
described, this information is not available in
the DWARF information. From the statement
trace can be derived which program branch
was taken. In the case of direct jumps, it can
also be determined, with some effort, which
branches were not taken. At the latest, in the
case of indirect jumps with almost any num-
ber of jump targets, it can de facto however
no longer be determined how many branches
actually exist and where they lead.
In order to avoid the equally extensive and
error-prone static code analysis usual in such
cases, it is appropriate to use the basic block
information, which is available to the com-
piler after all program transformations. These
include, among other things, basic blocks
according to the function, identification num-
ber, address, size, the successor of a basic block
and the number of basic blocks. This informa-
tion is sufficient in order to determine a graph
of basic blocks and to filter out decision cov-
erage from the relation between basic blocks
and statement trace. This debug information
is stored in the linker output file and evaluated
by the debug tool for coverage determination.
The additional information has no effect on
code generation, memory usage or run-time
behavior.
With help of the control-flow-information
that is available via the enhanced debug
information and the trace data of recorded
program executions, it is possible to non-in-
vasively carry out coverage measurements.
Typically, a test arrangement with the stor-
age of trace data in an external trace mem-
ory with a memory capacity in the gigabyte
range is sensible for this purpose. The trace
interface of choice for this purpose is a high-
speed serial interface based on the Aurora
Figure 1. The Universal Access Device 3+ (UAD 3+) with Aurora trace pod and 4 GB trace me-
mory enables a high data throughput and at the same time reliable coupling of the target system.
Figure 2. Overview diagram of the measured total coverage per module