diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-06 22:49:13 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-06 22:49:13 +0000 |
commit | 8ef50bf3d1c287b5013c3168de77a462dfce3495 (patch) | |
tree | 3467f3372c1195b1546172d89af2205a50b1866d /lib/profile/GCDAProfiling.c | |
parent | 11023dc647fd8f41418da90d59db138400d0f334 (diff) |
Notes
Diffstat (limited to 'lib/profile/GCDAProfiling.c')
-rw-r--r-- | lib/profile/GCDAProfiling.c | 127 |
1 files changed, 105 insertions, 22 deletions
diff --git a/lib/profile/GCDAProfiling.c b/lib/profile/GCDAProfiling.c index ce1b03c14de7e..7edf6829b4a57 100644 --- a/lib/profile/GCDAProfiling.c +++ b/lib/profile/GCDAProfiling.c @@ -20,6 +20,7 @@ |* \*===----------------------------------------------------------------------===*/ +#include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> @@ -45,6 +46,11 @@ typedef unsigned int uint64_t; */ /* + * The current file name we're outputting. Used primarily for error logging. + */ +static char *filename = NULL; + +/* * The current file we're outputting. */ static FILE *output_file = NULL; @@ -196,17 +202,37 @@ static void recursive_mkdir(char *filename) { } } -static void map_file() { +static int map_file() { fseek(output_file, 0L, SEEK_END); file_size = ftell(output_file); + /* A size of 0 is invalid to `mmap'. Return a fail here, but don't issue an + * error message because it should "just work" for the user. */ + if (file_size == 0) + return -1; + write_buffer = mmap(0, file_size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0); + if (write_buffer == (void *)-1) { + int errnum = errno; + fprintf(stderr, "profiling: %s: cannot map: %s\n", filename, + strerror(errnum)); + return -1; + } + return 0; } static void unmap_file() { - msync(write_buffer, file_size, MS_SYNC); - munmap(write_buffer, file_size); + if (msync(write_buffer, file_size, MS_SYNC) == -1) { + int errnum = errno; + fprintf(stderr, "profiling: %s: cannot msync: %s\n", filename, + strerror(errnum)); + } + + /* We explicitly ignore errors from unmapping because at this point the data + * is written and we don't care. + */ + (void)munmap(write_buffer, file_size); write_buffer = NULL; file_size = 0; } @@ -220,8 +246,8 @@ static void unmap_file() { * started at a time. */ void llvm_gcda_start_file(const char *orig_filename, const char version[4]) { - char *filename = mangle_filename(orig_filename); const char *mode = "r+b"; + filename = mangle_filename(orig_filename); /* Try just opening the file. */ new_file = 0; @@ -236,10 +262,11 @@ void llvm_gcda_start_file(const char *orig_filename, const char version[4]) { /* Try creating the directories first then opening the file. */ recursive_mkdir(filename); fd = open(filename, O_RDWR | O_CREAT, 0644); - if (!output_file) { + if (fd == -1) { /* Bah! It's hopeless. */ - fprintf(stderr, "profiling:%s: cannot open\n", filename); - free(filename); + int errnum = errno; + fprintf(stderr, "profiling: %s: cannot open: %s\n", filename, + strerror(errnum)); return; } } @@ -256,7 +283,14 @@ void llvm_gcda_start_file(const char *orig_filename, const char version[4]) { resize_write_buffer(WRITE_BUFFER_SIZE); memset(write_buffer, 0, WRITE_BUFFER_SIZE); } else { - map_file(); + if (map_file() == -1) { + /* mmap failed, try to recover by clobbering */ + new_file = 1; + write_buffer = NULL; + cur_buffer_size = 0; + resize_write_buffer(WRITE_BUFFER_SIZE); + memset(write_buffer, 0, WRITE_BUFFER_SIZE); + } } /* gcda file, version, stamp LLVM. */ @@ -264,8 +298,6 @@ void llvm_gcda_start_file(const char *orig_filename, const char version[4]) { write_bytes(version, 4); write_bytes("MVLL", 4); - free(filename); - #ifdef DEBUG_GCDAPROFILING fprintf(stderr, "llvmgcda: [%s]\n", orig_filename); #endif @@ -334,7 +366,7 @@ void llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) { if (val != (uint32_t)-1) { /* There are counters present in the file. Merge them. */ if (val != 0x01a10000) { - fprintf(stderr, "profiling:invalid magic number (0x%08x)\n", val); + fprintf(stderr, "profiling:invalid arc tag (0x%08x)\n", val); return; } @@ -368,21 +400,72 @@ void llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) { #endif } -void llvm_gcda_end_file() { - /* Write out EOF record. */ +void llvm_gcda_summary_info() { + const int obj_summary_len = 9; // length for gcov compatibility + uint32_t i; + uint32_t runs = 1; + uint32_t val = 0; + uint64_t save_cur_pos = cur_pos; + if (!output_file) return; - write_bytes("\0\0\0\0\0\0\0\0", 8); - if (new_file) { - fwrite(write_buffer, cur_pos, 1, output_file); - free(write_buffer); - } else { - unmap_file(); + val = read_32bit_value(); + + if (val != (uint32_t)-1) { + /* There are counters present in the file. Merge them. */ + if (val != 0xa1000000) { + fprintf(stderr, "profiling:invalid object tag (0x%08x)\n", val); + return; + } + + val = read_32bit_value(); // length + if (val != obj_summary_len) { + fprintf(stderr, "profiling:invalid object length (%d)\n", val); // length + return; + } + + read_32bit_value(); // checksum, unused + read_32bit_value(); // num, unused + runs += read_32bit_value(); // add previous run count to new counter } - fclose(output_file); - output_file = NULL; - write_buffer = NULL; + cur_pos = save_cur_pos; + + /* Object summary tag */ + write_bytes("\0\0\0\xa1", 4); + write_32bit_value(obj_summary_len); + write_32bit_value(0); // checksum, unused + write_32bit_value(0); // num, unused + write_32bit_value(runs); + for (i = 3; i < obj_summary_len; ++i) + write_32bit_value(0); + + /* Program summary tag */ + write_bytes("\0\0\0\xa3", 4); // tag indicates 1 program + write_32bit_value(0); // 0 length + +#ifdef DEBUG_GCDAPROFILING + fprintf(stderr, "llvmgcda: %u runs\n", runs); +#endif +} + +void llvm_gcda_end_file() { + /* Write out EOF record. */ + if (output_file) { + write_bytes("\0\0\0\0\0\0\0\0", 8); + + if (new_file) { + fwrite(write_buffer, cur_pos, 1, output_file); + free(write_buffer); + } else { + unmap_file(); + } + + fclose(output_file); + output_file = NULL; + write_buffer = NULL; + } + free(filename); #ifdef DEBUG_GCDAPROFILING fprintf(stderr, "llvmgcda: -----\n"); |