Skip Navigation Links | |
Exit Print View | |
![]() |
Oracle Solaris Studio 12.3: Discover and Uncover User's Guide Oracle Solaris Studio 12.3 Information Library |
2. Memory Error Discovery Tool (Discover)
3. Code Coverage Tool (Uncover)
Requirements for Using Uncover
Running the Instrumented Binary
Generating and Viewing the Coverage Report
Understanding the Coverage Report in the Performance Analyzer
Understanding the ASCII Coverage Report
Uncover 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.
Specifically excluded from preparation are assembly language modules and functions that contain asm statements or .il templates.
Uncover 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.
Consider 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, but the compiler is likely to remove this code, so Uncover will not see it during instrumentation. So no coverage will be reported for these instructions.
The following is an example of 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
So 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. }
The following is an example of 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 may 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
So 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. }