GCDAProfiling.c revision d4ec0547a210f9f2f34e0c4631586a179bd97571
1b1928704201034c785a26296a49f69355eb56a05Nick Lewycky/*===- GCDAProfiling.c - Support library for GCDA file emission -----------===*\ 2b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* 3b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* The LLVM Compiler Infrastructure 4b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* 5b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* This file is distributed under the University of Illinois Open Source 6b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* License. See LICENSE.TXT for details. 7b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* 8b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|*===----------------------------------------------------------------------===*| 9b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* 10b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* This file implements the call back routines for the gcov profiling 11b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* instrumentation pass. Link against this library when running code through 12b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* the -insert-gcov-profiling LLVM pass. 13b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* 14b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* We emit files in a corrupt version of GCOV's "gcda" file format. These files 15b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* are only close enough that LCOV will happily parse them. Anything that lcov 16b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* ignores is missing. 17b1928704201034c785a26296a49f69355eb56a05Nick Lewycky|* 181790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky|* TODO: gcov is multi-process safe by having each exit open the existing file 191790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky|* and append to it. We'd like to achieve that and be thread-safe too. 201790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky|* 21b1928704201034c785a26296a49f69355eb56a05Nick Lewycky\*===----------------------------------------------------------------------===*/ 22b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 23b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/Support/DataTypes.h" 24b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include <stdio.h> 25b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include <stdlib.h> 26b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include <string.h> 275e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky#include <sys/stat.h> 285e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky#include <sys/types.h> 2970b582ab9c6d69ff1ba14c90c016da61477fc9dcBenjamin Kramer#ifdef _WIN32 3097938081f321bc08ded74fc452523c35b7f9f17eFrancois Pichet#include <direct.h> 3197938081f321bc08ded74fc452523c35b7f9f17eFrancois Pichet#endif 32b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 33ece78a30bdd4c26edcd5304aca1415ebc8b27756Nick Lewycky/* #define DEBUG_GCDAPROFILING */ 34b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 35b1928704201034c785a26296a49f69355eb56a05Nick Lewycky/* 36b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * --- GCOV file format I/O primitives --- 37b1928704201034c785a26296a49f69355eb56a05Nick Lewycky */ 38b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 39b1928704201034c785a26296a49f69355eb56a05Nick Lewyckystatic FILE *output_file = NULL; 40b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 41b1928704201034c785a26296a49f69355eb56a05Nick Lewyckystatic void write_int32(uint32_t i) { 42b1928704201034c785a26296a49f69355eb56a05Nick Lewycky fwrite(&i, 4, 1, output_file); 43b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 44b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 45b1928704201034c785a26296a49f69355eb56a05Nick Lewyckystatic void write_int64(uint64_t i) { 46b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t lo, hi; 47571c0e95fa74c570f1c42f15b63ba8c68cba86b1Benjamin Kramer lo = i >> 0; 48571c0e95fa74c570f1c42f15b63ba8c68cba86b1Benjamin Kramer hi = i >> 32; 49b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 50b1928704201034c785a26296a49f69355eb56a05Nick Lewycky write_int32(lo); 51b1928704201034c785a26296a49f69355eb56a05Nick Lewycky write_int32(hi); 52b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 53b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 545409a188328d9de3755febc23558d4fc1797d04eNick Lewyckystatic uint32_t length_of_string(const char *s) { 55d363ff334d796c7f3df834d928a10d88ed758454Nick Lewycky return (strlen(s) / 4) + 1; 565409a188328d9de3755febc23558d4fc1797d04eNick Lewycky} 575409a188328d9de3755febc23558d4fc1797d04eNick Lewycky 585409a188328d9de3755febc23558d4fc1797d04eNick Lewyckystatic void write_string(const char *s) { 595409a188328d9de3755febc23558d4fc1797d04eNick Lewycky uint32_t len = length_of_string(s); 605409a188328d9de3755febc23558d4fc1797d04eNick Lewycky write_int32(len); 615409a188328d9de3755febc23558d4fc1797d04eNick Lewycky fwrite(s, strlen(s), 1, output_file); 625409a188328d9de3755febc23558d4fc1797d04eNick Lewycky fwrite("\0\0\0\0", 4 - (strlen(s) % 4), 1, output_file); 635409a188328d9de3755febc23558d4fc1797d04eNick Lewycky} 645409a188328d9de3755febc23558d4fc1797d04eNick Lewycky 657a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewyckystatic char *mangle_filename(const char *orig_filename) { 667a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky /* TODO: handle GCOV_PREFIX_STRIP */ 677a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky const char *prefix; 687a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky char *filename = 0; 697a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky 707a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky prefix = getenv("GCOV_PREFIX"); 717a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky 727a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky if (!prefix) 73d006ddc195934cf896d2f5e512d38e196923c79bNick Lewycky return strdup(orig_filename); 747a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky 757a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky filename = malloc(strlen(prefix) + 1 + strlen(orig_filename) + 1); 767a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky strcpy(filename, prefix); 777a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky strcat(filename, "/"); 787a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky strcat(filename, orig_filename); 797a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky 807a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky return filename; 817a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky} 827a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky 835e436b3b0ef06258ed2d7929946eb00684973183Nick Lewyckystatic void recursive_mkdir(const char *filename) { 845e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky char *pathname; 855e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky int i, e; 865e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky 875e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky for (i = 1, e = strlen(filename); i != e; ++i) { 885e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky if (filename[i] == '/') { 895e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky pathname = malloc(i + 1); 905e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky strncpy(pathname, filename, i); 915e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky pathname[i] = '\0'; 92aeebc35886726c8d378033d7122f29feba5d4134Eli Friedman#ifdef _WIN32 9397938081f321bc08ded74fc452523c35b7f9f17eFrancois Pichet _mkdir(pathname); 9497938081f321bc08ded74fc452523c35b7f9f17eFrancois Pichet#else 955e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky mkdir(pathname, 0750); /* some of these will fail, ignore it. */ 9697938081f321bc08ded74fc452523c35b7f9f17eFrancois Pichet#endif 975e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky free(pathname); 985e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky } 995e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky } 1005e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky} 1015e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky 102b1928704201034c785a26296a49f69355eb56a05Nick Lewycky/* 103b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * --- LLVM line counter API --- 104b1928704201034c785a26296a49f69355eb56a05Nick Lewycky */ 105b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 106b1928704201034c785a26296a49f69355eb56a05Nick Lewycky/* A file in this case is a translation unit. Each .o file built with line 107b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * profiling enabled will emit to a different file. Only one file may be 108b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * started at a time. 109b1928704201034c785a26296a49f69355eb56a05Nick Lewycky */ 1107a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewyckyvoid llvm_gcda_start_file(const char *orig_filename) { 1117a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky char *filename; 1127a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky filename = mangle_filename(orig_filename); 1135e436b3b0ef06258ed2d7929946eb00684973183Nick Lewycky recursive_mkdir(filename); 1147a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky output_file = fopen(filename, "wb"); 115b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 11666e30f8db180bdc0fba637c84e7b72396a08d8f2Bill Wendling if (!output_file) { 1177242a4fb86d9b369a467e3a85ce02bc94c6d9dc8Bill Wendling const char *cptr = strrchr(orig_filename, '/'); 1187242a4fb86d9b369a467e3a85ce02bc94c6d9dc8Bill Wendling output_file = fopen(cptr ? cptr + 1 : orig_filename, "wb"); 11966e30f8db180bdc0fba637c84e7b72396a08d8f2Bill Wendling 12066e30f8db180bdc0fba637c84e7b72396a08d8f2Bill Wendling if (!output_file) { 12166e30f8db180bdc0fba637c84e7b72396a08d8f2Bill Wendling fprintf(stderr, "LLVM profiling runtime: while opening '%s': ", 122d4ec0547a210f9f2f34e0c4631586a179bd97571Bill Wendling cptr ? cptr + 1 : orig_filename); 12366e30f8db180bdc0fba637c84e7b72396a08d8f2Bill Wendling perror(""); 12466e30f8db180bdc0fba637c84e7b72396a08d8f2Bill Wendling exit(1); 12566e30f8db180bdc0fba637c84e7b72396a08d8f2Bill Wendling } 12666e30f8db180bdc0fba637c84e7b72396a08d8f2Bill Wendling } 12766e30f8db180bdc0fba637c84e7b72396a08d8f2Bill Wendling 128b1928704201034c785a26296a49f69355eb56a05Nick Lewycky /* gcda file, version 404*, stamp LLVM. */ 129ad759c5a073dbd66d3297347c64da3ab148a92a4Bill Wendling#ifdef __APPLE__ 130ad759c5a073dbd66d3297347c64da3ab148a92a4Bill Wendling fwrite("adcg*204MVLL", 12, 1, output_file); 131ad759c5a073dbd66d3297347c64da3ab148a92a4Bill Wendling#else 132b1928704201034c785a26296a49f69355eb56a05Nick Lewycky fwrite("adcg*404MVLL", 12, 1, output_file); 133ad759c5a073dbd66d3297347c64da3ab148a92a4Bill Wendling#endif 134b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 135b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#ifdef DEBUG_GCDAPROFILING 1367a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky printf("llvmgcda: [%s]\n", orig_filename); 1371790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky#endif 1387a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky 1397a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky free(filename); 1401790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky} 1411790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 1421790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky/* Given an array of pointers to counters (counters), increment the n-th one, 1431790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky * where we're also given a pointer to n (predecessor). 1441790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky */ 1451790c9cbb6714e81eab1412909a2320acaecc43bNick Lewyckyvoid llvm_gcda_increment_indirect_counter(uint32_t *predecessor, 1461790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky uint64_t **counters) { 1471790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky uint64_t *counter; 1487a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky uint32_t pred; 1497a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky 1507a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky pred = *predecessor; 1517a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky if (pred == 0xffffffff) 1521790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return; 1537a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky counter = counters[pred]; 1541790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 1551790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky /* Don't crash if the pred# is out of sync. This can happen due to threads, 1561790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky or because of a TODO in GCOVProfiling.cpp buildEdgeLookupTable(). */ 1577a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky if (counter) 1581790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky ++*counter; 1591790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky#ifdef DEBUG_GCDAPROFILING 1601790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky else 1611790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky printf("llvmgcda: increment_indirect_counter counters=%x, pred=%u\n", 1621790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky state_table_row, *predecessor); 163b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#endif 164b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 165b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1665409a188328d9de3755febc23558d4fc1797d04eNick Lewyckyvoid llvm_gcda_emit_function(uint32_t ident, const char *function_name) { 167b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#ifdef DEBUG_GCDAPROFILING 1681790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky printf("llvmgcda: function id=%x\n", ident); 169b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#endif 170b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 171b1928704201034c785a26296a49f69355eb56a05Nick Lewycky /* function tag */ 172b1928704201034c785a26296a49f69355eb56a05Nick Lewycky fwrite("\0\0\0\1", 4, 1, output_file); 1735409a188328d9de3755febc23558d4fc1797d04eNick Lewycky write_int32(3 + 1 + length_of_string(function_name)); 174b1928704201034c785a26296a49f69355eb56a05Nick Lewycky write_int32(ident); 175b1928704201034c785a26296a49f69355eb56a05Nick Lewycky write_int32(0); 1765409a188328d9de3755febc23558d4fc1797d04eNick Lewycky write_int32(0); 1775409a188328d9de3755febc23558d4fc1797d04eNick Lewycky write_string(function_name); 178b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 179b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 180b1928704201034c785a26296a49f69355eb56a05Nick Lewyckyvoid llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) { 181b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t i; 182b1928704201034c785a26296a49f69355eb56a05Nick Lewycky /* counter #1 (arcs) tag */ 183b1928704201034c785a26296a49f69355eb56a05Nick Lewycky fwrite("\0\0\xa1\1", 4, 1, output_file); 184b1928704201034c785a26296a49f69355eb56a05Nick Lewycky write_int32(num_counters * 2); 185b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (i = 0; i < num_counters; ++i) { 186b1928704201034c785a26296a49f69355eb56a05Nick Lewycky write_int64(counters[i]); 187b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 188b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 189b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#ifdef DEBUG_GCDAPROFILING 1901790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky printf("llvmgcda: %u arcs\n", num_counters); 191b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (i = 0; i < num_counters; ++i) { 1921790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky printf("llvmgcda: %llu\n", (unsigned long long)counters[i]); 193b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 194b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#endif 195b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 196b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 197b1928704201034c785a26296a49f69355eb56a05Nick Lewyckyvoid llvm_gcda_end_file() { 198b1928704201034c785a26296a49f69355eb56a05Nick Lewycky /* Write out EOF record. */ 199b1928704201034c785a26296a49f69355eb56a05Nick Lewycky fwrite("\0\0\0\0\0\0\0\0", 8, 1, output_file); 200b1928704201034c785a26296a49f69355eb56a05Nick Lewycky fclose(output_file); 201b1928704201034c785a26296a49f69355eb56a05Nick Lewycky output_file = NULL; 202b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 203b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#ifdef DEBUG_GCDAPROFILING 2041790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky printf("llvmgcda: -----\n"); 205b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#endif 206b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 207