This section describes known limitations when using uncover.
The uncover utility can instrument only code that has been prepared as described in Requirements for Using uncover. Non-annotated code might come from assembly language code linked into the binary or from modules compiled with older compilers or operating systems than those listed in that section.
uncover cannot instrument assembly language modules or functions that contain asm statements or .il templates.
uncover is incompatible with binaries built with any of the following compiler options:
–p
–pg
–qp
–xpg
–xlinkopt
The uncover utility operates on machine code. It finds coverage of machine instructions and then correlates this coverage with source code. Some source code statements do not have associated machine instructions, so uncover might appear to not report coverage for such statements.
Example 4 Simple ExampleConsider the following code fragment:
#define A 100 #define B 200 ... if (A>B) { ... }
You might expect uncover to report a non-zero execution count for the if statement. However, the compiler is likely to remove this code. uncover will not detect it during instrumentation and no coverage will be reported for these instructions.
Example 5 Dead Code ExampleThe following example shows dead code:
1 void foo() 2 { 3 A(); 4 return; 5 B(); 6 C(); 7 D(); 8 return; 9 }
Corresponding assembly shows that calls to B,C,D are deleted because this code is never executed.
foo: .L900000109: /* 000000 2 */ save %sp,-96,%sp /* 0x0004 3 */ call A ! params = ! Result = /* 0x0008 */ nop /* 0x000c 8 */ ret ! Result = /* 0x0010 */ restore %g0,%g0,%g0
Therefore, no coverage will be reported for lines 5 through 6.
Excl. Excl. Excl. Excl. Excl. Uncoverage Function Instr Block Instr Count Exec Covered % Covered % 1. void foo() ## 0 1 1 100 100 2. { <Function: foo ## 0 0 2 0 0 3. A(); 4. return; 5. B(); 6. C(); 7. D(); 8. return; ## 0 0 2 0 0 9. }Example 6 Redundant Code Example
The following example shows redundant code:
1 int g; 2 int foo() { 3 int x; 4 x = g; 5 for (int i=0; i<100; i++) 6 x++; 7 return x; 8 }
At low optimization levels, the compiler can generate code for all the lines:
foo: .L900000107: /* 000000 3 */ save %sp,-112,%sp /* 0x0004 5 */ sethi %hi(g),%l1 /* 0x0008 */ ld [%l1+%lo(g)],%l3 ! volatile /* 0x000c */ add %l1,%lo(g),%l2 /* 0x0010 6 */ st %g0,[%fp-12] /* 0x0014 5 */ st %l3,[%fp-8] /* 0x0018 6 */ ld [%fp-12],%l4 /* 0x001c */ cmp %l4,100 /* 0x0020 */ bge,a,pn %icc,.L900000105 /* 0x0024 8 */ ld [%fp-8],%l1 .L17: /* 0x0028 7 */ ld [%fp-8],%l1 .L900000104: /* 0x002c 6 */ ld [%fp-12],%l3 /* 0x0030 7 */ add %l1,1,%l2 /* 0x0034 */ st %l2,[%fp-8] /* 0x0038 6 */ add %l3,1,%l4 /* 0x003c */ st %l4,[%fp-12] /* 0x0040 */ ld [%fp-12],%l5 /* 0x0044 */ cmp %l5,100 /* 0x0048 */ bl,a,pn %icc,.L900000104 /* 0x004c 7 */ ld [%fp-8],%l1 /* 0x0050 8 */ ld [%fp-8],%l1 .L900000105: /* 0x0054 8 */ st %l1,[%fp-4] /* 0x0058 */ ld [%fp-4],%i0 /* 0x005c */ ret ! Result = %i0 /* 0x0060 */ restore %g0,%g0,%g0
At high optimization levels, most of the executable source lines do not have any corresponding instructions:
foo: /* 000000 5 */ sethi %hi(g),%o5 /* 0x0004 */ ld [%o5+%lo(g)],%o4 /* 0x0008 8 */ retl ! Result = %o0 /* 0x000c 5 */ add %o4,100,%o0
Therefore, no coverage will be reported for some lines.
Excl. Excl. Excl. Excl. Excl. Uncoverage Function Instr Block Instr Count Exec Covered % Covered % 1. int g; 0 0 0 0 0 2. int foo() { <Function foo> 3. int x; 4. x = g; Source loop below has tag L1 Induction variable substitution performed on L1 L1 deleted as dead code ## 0 1 3 100 100 5. for (int i=0; i<100; i++) 6. x++; 7. return x; 0 0 1 0 0 8. }