Menu

Searches titles, sections and text. ↑ ↓ to move, Enter to open, Esc to close. Opens with / or Ctrl+K.

    Contact

    Source attribution in trace-based code coverage

    How machine execution is attributed to source-level coverage obligations, why optimization creates ambiguity, and how the three methods differ.


    Source attribution is the ability to assign observed machine-level execution to the correct source-level coverage obligation without ambiguity.

    In brief

    Instruction trace reports machine-level execution. Source-level code coverage additionally requires a defensible relationship between the observed machine events and the corresponding source obligations.

    Compiler optimization can merge, predicate, clone or remove source structures. A trace can therefore be complete while only part of the execution can be attributed unambiguously to individual source-level decisions or conditions.

    Three different questions

    Trace completeness

    Did the observation system capture the relevant machine-level execution without an invalidating trace gap?

    Source attribution

    Can each relevant machine-level event be assigned to the correct source-level obligation without ambiguity?

    Coverage achieved

    Did the attributable source obligation receive the executions required by the selected coverage criterion?

    These properties must not be collapsed into one percentage.

    Why optimization affects attribution

    The relationship between source code and object code is not necessarily one-to-one.

    An optimizing compiler may:

    • remove a branch whose outcome can be calculated earlier;
    • merge several source decisions into one machine branch;
    • clone one source expression into several machine locations;
    • use predicated or branchless instructions;
    • fold constant conditions;
    • inline functions;
    • share common tails;
    • transform short-circuit evaluation.

    The resulting execution may remain fully visible at machine level. The difficulty is determining which source obligation the observed event represents. The mechanics are worked through, with figures, in object-to-source mapping.

    How the three observation paths preserve source identity

    Native trace and debug information

    The original optimized binary contains no coverage counters or anchors. Instruction trace reconstructs machine-level control flow, while debug information and object-code analysis provide the relationship to source structures.

    This path preserves the original application instruction stream. Attribution is limited where optimization has removed or made the source-to-object relationship ambiguous.

    CEDARtools.Anchor

    Anchor* supplements selected paths and conditions with named control-flow anchors. It is designed to preserve the identity of selected source obligations through those anchors. Attribution is accepted only where the expected anchor is present, uniquely resolved and linked to the intended obligation by the validated manifest and object mapping. A missing, colliding or unresolved anchor leaves the corresponding obligation unresolved rather than silently attributed. Execution of the anchors is observed through hardware trace and evaluated outside the target.

    The anchors occupy code space and may affect layout. They do not maintain application-side coverage counters or analysis state in RAM. The method has its own page: CEDARtools.Anchor.

    GCC coverage instrumentation

    GCC places compiler-generated observation points and counters into the program. These counters preserve the identities selected by the compiler’s instrumentation model.

    This source identity is obtained through additional code, metadata, runtime updates and RAM state. That is a cost question with its own trade-offs - code size, timing and memory - and there are configurations where it is still the right answer.

    Measured example

    In the SQLite -O3 comparison, native trace supported unambiguous attribution for 77% (5,667 of 7,356) of the decision obligations linked into the image. At the condition level, 48.2% of the conditions in compound decisions were attributable and 51.6% of the compound decisions were completely derivable.

    These figures do not describe trace loss. They describe the source identity recoverable from the optimized native binary under the analysis used in this experiment.

    Read the complete SQLite Evidence Record

    In this context, the following expressions refer to closely related aspects of the same problem:

    • source attribution;
    • source-level attribution;
    • trace-to-source attribution;
    • source-to-object attribution;
    • source-to-object mapping;
    • attribution of machine execution to source-level obligations.

    This page uses source attribution in trace-based code coverage as the canonical term.

    What this page establishes

    • machine-level trace and source-level evidence are different layers;
    • optimization can reduce source attribution without causing trace loss;
    • native trace, Anchor* and GCC provide different mechanisms for retaining or reconstructing source identity, each with its own validity conditions and target-side effects;
    • attribution must be reported separately from coverage achieved.

    Limitations

    The achievable attribution depends on the compiler, optimization level, debug information, instruction set, trace protocol, source construct and analysis method. No percentage from one workload should be generalized to another.

    Sources

    The measured figures on this page come from our own measurement campaign, documented in the SQLite -O3 Evidence Record with its setup, evidence status and dataset downloads. The compiler-behavior statements reflect standard optimization techniques as documented for optimizing compilers and are worked through with concrete object-code examples in object-to-source mapping and DWARF under optimization.

    Apply this to your target

    Send the exact processor, board, trace path, compiler and metric you need. We will review feasibility at configuration level rather than answering from the core-family name alone.

    Start a target feasibility review