you can use windbg wt (watch and trace function to generate an execution flow) the demo below is for the code in your query compiled in debug mode (to ensure function calls exist and not optimised away by a simple substitution) code used for example compiled in msvcpp2ktenexp debug int glob = 0; void f1(int a) { printf("%d ",a); glob++;} void f3(int a) { printf("F3 %d ",a);} void f5(int a) { printf("F5 %d ",a);} void f6(int a) { printf("%d ",a);} void f4(int a) { f5(5);} void f2(int a) { if(glob == 8) { f3(3); f4(4); } else { f6(6); } } void main() { rndrob:f1(1);f2(2);f1(1);f2(2);if(glob<10){goto rndrob;} } dry run results >flowt.exe 1 6 1 6 1 6 1 6 1 6 1 6 1 6 1 F3 3 F5 5 1 6 1 6 windbg wt results for module flowt function main() edited to remove fluff statistics at the end shows printf() was called 21 times f3() f4() once etc etc **:\>cdb -c "g main;wt -m flowt" flowt.exe** Tracing flowt!main to return address 00411bcf 59 0 [ 0] flowt!main 62 0 [ 1] flowt!f1 1 72 0 [ 2] MSVCR100D!printf 65 72 [ 1] flowt!f1 62 156 [ 0] flowt!main 61 0 [ 1] flowt!f2 62 0 [ 2] flowt!f6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 61 0 [ 1] flowt!f2 62 0 [ 2] flowt!f3 F3 3 72 0 [ 3] MSVCR100D!printf XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 64 153 [ 1] flowt!f2 62 0 [ 3] flowt!f5 F5 5 72 0 [ 4] MSVCR100D!printf 65 72 [ 3] flowt!f5 141 4073 [ 0] flowt!main 4214 instructions were executed in 4213 events (0 from other threads) Function Name Invocations MinInst MaxInst AvgInst MSVCR100D!printf 21 72 72 72 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX flowt!f1 10 77 77 77 flowt!f2 10 71 75 71 flowt!f3 1 74 74 74 flowt!f4 1 69 69 69 flowt!f5 1 74 74 74 flowt!f6 9 74 74 74 flowt!main 1 141 141 141