diff options
Diffstat (limited to 'lib/profile/GCDAProfiling.c')
-rw-r--r-- | lib/profile/GCDAProfiling.c | 93 |
1 files changed, 59 insertions, 34 deletions
diff --git a/lib/profile/GCDAProfiling.c b/lib/profile/GCDAProfiling.c index fd506e9..8f92a91 100644 --- a/lib/profile/GCDAProfiling.c +++ b/lib/profile/GCDAProfiling.c @@ -49,10 +49,8 @@ static void write_int32(uint32_t i) { } static void write_int64(uint64_t i) { - uint32_t lo, hi; - lo = i >> 0; - hi = i >> 32; - + uint32_t lo = i >> 0; + uint32_t hi = i >> 32; write_int32(lo); write_int32(hi); } @@ -69,39 +67,55 @@ static void write_string(const char *s) { } static char *mangle_filename(const char *orig_filename) { - /* TODO: handle GCOV_PREFIX_STRIP */ - const char *prefix; char *filename = 0; - - prefix = getenv("GCOV_PREFIX"); + int prefix_len = 0; + int prefix_strip = 0; + int level = 0; + const char *fname = orig_filename, *ptr = NULL; + const char *prefix = getenv("GCOV_PREFIX"); + const char *tmp = getenv("GCOV_PREFIX_STRIP"); if (!prefix) return strdup(orig_filename); - filename = malloc(strlen(prefix) + 1 + strlen(orig_filename) + 1); + if (tmp) { + prefix_strip = atoi(tmp); + + /* Negative GCOV_PREFIX_STRIP values are ignored */ + if (prefix_strip < 0) + prefix_strip = 0; + } + + prefix_len = strlen(prefix); + filename = malloc(prefix_len + 1 + strlen(orig_filename) + 1); strcpy(filename, prefix); - strcat(filename, "/"); - strcat(filename, orig_filename); + + if (prefix[prefix_len - 1] != '/') + strcat(filename, "/"); + + for (ptr = fname + 1; *ptr != '\0' && level < prefix_strip; ++ptr) { + if (*ptr != '/') continue; + fname = ptr; + ++level; + } + + strcat(filename, fname); return filename; } -static void recursive_mkdir(const char *filename) { - char *pathname; - int i, e; +static void recursive_mkdir(char *filename) { + int i; - for (i = 1, e = strlen(filename); i != e; ++i) { - if (filename[i] == '/') { - pathname = malloc(i + 1); - strncpy(pathname, filename, i); - pathname[i] = '\0'; + for (i = 1; filename[i] != '\0'; ++i) { + if (filename[i] != '/') continue; + filename[i] = '\0'; #ifdef _WIN32 - _mkdir(pathname); + _mkdir(filename); #else - mkdir(pathname, 0750); /* some of these will fail, ignore it. */ + mkdir(filename, 0755); /* Some of these will fail, ignore it. */ #endif - free(pathname); - } + filename[i] = '/'; } } @@ -114,10 +128,18 @@ static void recursive_mkdir(const char *filename) { * started at a time. */ void llvm_gcda_start_file(const char *orig_filename) { - char *filename; - filename = mangle_filename(orig_filename); - recursive_mkdir(filename); - output_file = fopen(filename, "wb"); + char *filename = mangle_filename(orig_filename); + output_file = fopen(filename, "w+b"); + + if (!output_file) { + recursive_mkdir(filename); + output_file = fopen(filename, "w+b"); + if (!output_file) { + fprintf(stderr, "profiling:%s: cannot open\n", filename); + free(filename); + return; + } + } /* gcda file, version 404*, stamp LLVM. */ #ifdef __APPLE__ @@ -152,8 +174,9 @@ void llvm_gcda_increment_indirect_counter(uint32_t *predecessor, ++*counter; #ifdef DEBUG_GCDAPROFILING else - printf("llvmgcda: increment_indirect_counter counters=%x, pred=%u\n", - state_table_row, *predecessor); + fprintf(stderr, + "llvmgcda: increment_indirect_counter counters=%x, pred=%u\n", + state_table_row, *predecessor); #endif } @@ -161,6 +184,7 @@ void llvm_gcda_emit_function(uint32_t ident, const char *function_name) { #ifdef DEBUG_GCDAPROFILING printf("llvmgcda: function id=%x\n", ident); #endif + if (!output_file) return; /* function tag */ fwrite("\0\0\0\1", 4, 1, output_file); @@ -173,23 +197,24 @@ void llvm_gcda_emit_function(uint32_t ident, const char *function_name) { void llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) { uint32_t i; - /* counter #1 (arcs) tag */ + + /* Counter #1 (arcs) tag */ + if (!output_file) return; fwrite("\0\0\xa1\1", 4, 1, output_file); write_int32(num_counters * 2); - for (i = 0; i < num_counters; ++i) { + for (i = 0; i < num_counters; ++i) write_int64(counters[i]); - } #ifdef DEBUG_GCDAPROFILING printf("llvmgcda: %u arcs\n", num_counters); - for (i = 0; i < num_counters; ++i) { + for (i = 0; i < num_counters; ++i) printf("llvmgcda: %llu\n", (unsigned long long)counters[i]); - } #endif } void llvm_gcda_end_file() { /* Write out EOF record. */ + if (!output_file) return; fwrite("\0\0\0\0\0\0\0\0", 8, 1, output_file); fclose(output_file); output_file = NULL; |