Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <inttypes.h>
  5.  
  6. #define MAX_COVERED_CODE_SIZE (256*1024)
  7.  
  8. typedef struct {
  9.     uint64_t to_cnt, from_cnt;
  10. } branch;
  11.  
  12. branch branches[MAX_COVERED_CODE_SIZE];
  13.  
  14. uint32_t coverage_offset, coverage_begin, coverage_end;
  15.  
  16. void read_coverage_file(const char *fname) {
  17.     FILE *f = fopen(fname, "r");
  18.     fseeko(f, 0, SEEK_END);
  19.     off_t fsize = ftello(f);
  20.     fseeko(f, 0, SEEK_SET);
  21.     fread(&coverage_begin, sizeof(uint32_t), 1, f);
  22.     fread(&coverage_end, sizeof(uint32_t), 1, f);
  23.     size_t branch_cnt = (fsize-4*2)/(2*4);
  24.     for (size_t i = 0; i < branch_cnt; i++) {
  25.         uint32_t from, to;
  26.         fread(&from, sizeof(uint32_t), 1, f);
  27.         fread(&to, sizeof(uint32_t), 1, f);
  28.         if (from >= coverage_begin && from < coverage_end) {
  29.             from = from - coverage_begin + coverage_offset;
  30.             branches[from].from_cnt++;
  31.         }
  32.         if (to >= coverage_begin && to < coverage_end) {
  33.             to = to - coverage_begin + coverage_offset;
  34.             branches[to].to_cnt++;
  35.         }
  36.     }
  37.     fclose(f);
  38. }
  39.  
  40. size_t count_line_bytes(const char *s) {
  41.     size_t cnt = 0;
  42.     for (size_t i = 10; i <= 58; i += 3) {
  43.         if (s[i] == ' ') break;
  44.         cnt++;
  45.     }
  46.     return cnt;
  47. }
  48.  
  49. size_t count_block_bytes(FILE *f) {
  50.     char tmp[1024];
  51.     size_t cnt = 0;
  52.     if (fgets(tmp, 1024, f) && strspn(tmp, "0123456789ABCDEF") == 8) {
  53.         cnt = count_line_bytes(tmp);
  54.         while (fgets(tmp, 1024, f) && tmp[0] == ' ' && tmp[10] != ' ') {
  55.             cnt += count_line_bytes(tmp);
  56.         }
  57.     }
  58.     return cnt;
  59. }
  60.  
  61. int is_cond_jump(const char *s) {
  62.     s += strspn(s, " \t");
  63.     int found = !strncmp(s, "jo", 2)
  64.                 || !strncmp(s, "jno", 3)
  65.                 || !strncmp(s, "js", 2)
  66.                 || !strncmp(s, "jns", 3)
  67.                 || !strncmp(s, "je", 2)
  68.                 || !strncmp(s, "jne", 3)
  69.                 || !strncmp(s, "jz", 2)
  70.                 || !strncmp(s, "jnz", 3)
  71.                 || !strncmp(s, "jb", 2)
  72.                 || !strncmp(s, "jnb", 3)
  73.                 || !strncmp(s, "jc", 2)
  74.                 || !strncmp(s, "jnc", 3)
  75.                 || !strncmp(s, "jae", 3)
  76.                 || !strncmp(s, "jnae", 4)
  77.                 || !strncmp(s, "jbe", 3)
  78.                 || !strncmp(s, "jna", 3)
  79.                 || !strncmp(s, "ja", 2)
  80.                 || !strncmp(s, "jnbe", 4)
  81.                 || !strncmp(s, "jl", 2)
  82.                 || !strncmp(s, "jnge", 4)
  83.                 || !strncmp(s, "jge", 3)
  84.                 || !strncmp(s, "jnl", 3)
  85.                 || !strncmp(s, "jle", 3)
  86.                 || !strncmp(s, "jng", 3)
  87.                 || !strncmp(s, "jg",2)
  88.                 || !strncmp(s, "jnle", 4)
  89.                 || !strncmp(s, "jp", 2)
  90.                 || !strncmp(s, "jpe", 3)
  91.                 || !strncmp(s, "jnp", 3)
  92.                 || !strncmp(s, "jpo", 3)
  93.                 || !strncmp(s, "jcxz", 4)
  94.                 || !strncmp(s, "jecxz", 5);
  95.     return found;
  96. }
  97.  
  98. int main(int argc, char **argv) {
  99.     if (argc < 4) {
  100.         fprintf(stderr, "usage: covpreproc <listing file> <coverage_begin offset> <coverage files ...>\n");
  101.         exit(1);
  102.     }
  103.     sscanf(argv[2], "%" SCNx32, &coverage_offset);
  104.  
  105.     for (int i = 3; i < argc; i++) {
  106.         read_coverage_file(argv[i]);
  107.     }
  108.  
  109.     FILE *f = fopen(argv[1], "r");
  110.     char tmp[1024];
  111.     uint64_t cur = 0, taken, not_taken;
  112.     while (1) {
  113.         off_t fpos_before = ftello(f);
  114.         if (!fgets(tmp, 1024, f)) {
  115.             break;
  116.         }
  117.         off_t fpos_after = ftello(f);
  118.         if (strspn(tmp, "0123456789ABCDEF") == 8) {
  119.             int is_cond = is_cond_jump(tmp + 64);
  120.             fseeko(f, fpos_before, SEEK_SET);
  121.             size_t inst_len = count_block_bytes(f);
  122.             fseeko(f, fpos_after, SEEK_SET);
  123.             unsigned long pos = strtoul(tmp, NULL, 16);
  124.             size_t total_to = 0, total_from = 0;
  125.             for (size_t i = 0; i < inst_len; i++) {
  126.                 if (pos + i < coverage_end - coverage_begin + coverage_offset) {
  127.                     total_to += branches[pos + i].to_cnt;
  128.                     total_from += branches[pos + i].from_cnt;
  129.                 }
  130.             }
  131.             cur += total_to;
  132.             if (is_cond) {
  133.                 taken = total_from;
  134.                 not_taken = cur - taken;
  135.                 if (taken && not_taken) {
  136.                     putchar(' ');
  137.                 } else {
  138.                     putchar('-');
  139.                 }
  140.             } else {
  141.                 putchar(' ');
  142.             }
  143.             if (cur) {
  144.                 putchar(' ');
  145.             } else {
  146.                 putchar('-');
  147.             }
  148.             if (is_cond) {
  149.                 int spaces = 19 - printf("%10" PRIu64 "/%" PRIu64, taken, not_taken);
  150.                 while (spaces-- > 0)
  151.                     putchar(' ');
  152.             } else {
  153.                 printf("                   ");
  154.             }
  155.             printf(" %10" PRIu64, cur);
  156.             cur -= total_from;
  157.         } else {
  158.             printf("                                ");
  159.         }
  160.         printf(" : %s", tmp + 64);
  161.     }
  162.     fclose(f);
  163.  
  164.     return 0;
  165. }
  166.