Index: compiler-rt/lib/profile/GCDAProfiling.c =================================================================== --- compiler-rt/lib/profile/GCDAProfiling.c +++ compiler-rt/lib/profile/GCDAProfiling.c @@ -19,8 +19,6 @@ |* \*===----------------------------------------------------------------------===*/ -#if !defined(__Fuchsia__) - #include #include #include @@ -31,6 +29,11 @@ #define WIN32_LEAN_AND_MEAN #include #include "WindowsMMap.h" +#elif defined(__Fuchsia__) +#include +#include +#include +#include #else #include #include @@ -76,7 +79,11 @@ /* * The current file we're outputting. */ +#ifdef __Fuchsia__ +static zx_handle_t output_file = ZX_HANDLE_INVALID; +#else static FILE *output_file = NULL; +#endif /* * Buffer that we write things into. @@ -85,12 +92,17 @@ static unsigned char *write_buffer = NULL; static uint64_t cur_buffer_size = 0; static uint64_t cur_pos = 0; -static uint64_t file_size = 0; static int new_file = 0; #if defined(_WIN32) static HANDLE mmap_handle = NULL; #endif +#ifdef __Fuchsia__ +static const size_t file_size = sizeof(void *) << 32; +static const char sink_name[] = "llvmgcda"; +#else +static uint64_t file_size = 0; static int fd = -1; +#endif typedef void (*fn_ptr)(); @@ -169,7 +181,16 @@ if (size <= cur_buffer_size) return; size = (size - 1) / WRITE_BUFFER_SIZE + 1; size *= WRITE_BUFFER_SIZE; +#ifdef __Fuchsia__ + zx_status_t status = _zx_vmo_set_size(output_file, size); + if (status != ZX_OK) { + fprintf(stderr, "profiling: failed to resize VMO: %s\n", + _zx_status_get_string(status)); + return; + } +#else write_buffer = realloc(write_buffer, size); +#endif cur_buffer_size = size; } @@ -234,6 +255,7 @@ return ((uint64_t)hi << 32) | ((uint64_t)lo); } +#ifndef __Fuchsia__ static char *mangle_filename(const char *orig_filename) { char *new_filename; size_t prefix_len; @@ -280,7 +302,7 @@ CloseHandle(mmap_handle); return -1; } -#else +#else /* _WIN32 */ write_buffer = mmap(0, file_size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0); if (write_buffer == (void *)-1) { @@ -289,7 +311,7 @@ strerror(errnum)); return -1; } -#endif +#endif /* _WIN32 */ return 0; } @@ -312,7 +334,7 @@ } mmap_handle = NULL; -#else +#else /* _WIN32 */ if (msync(write_buffer, file_size, MS_SYNC) == -1) { int errnum = errno; fprintf(stderr, "profiling: %s: cannot msync: %s\n", filename, @@ -323,11 +345,12 @@ * is written and we don't care. */ (void)munmap(write_buffer, file_size); -#endif +#endif /* _WIN32 */ write_buffer = NULL; file_size = 0; } +#endif /* __Fuchsia__ */ /* * --- LLVM line counter API --- @@ -340,6 +363,7 @@ COMPILER_RT_VISIBILITY void llvm_gcda_start_file(const char *orig_filename, const char version[4], uint32_t checksum) { +#ifndef __Fuchsia__ const char *mode = "r+b"; filename = mangle_filename(orig_filename); @@ -391,6 +415,65 @@ memset(write_buffer, 0, WRITE_BUFFER_SIZE); } } +#else /* __Fuchsia__ */ + /* Create VMO to hold the profile data. */ + zx_status_t status = _zx_vmo_create(WRITE_BUFFER_SIZE, 0, &output_file); + if (status != ZX_OK) { + lprofReport("profiling: cannot create VMO: %s\n", + _zx_status_get_string(status)); + return; + } + + /* Get information about the current process. */ + zx_info_handle_basic_t info; + status = _zx_object_get_info(_zx_process_self(), ZX_INFO_HANDLE_BASIC, &info, + sizeof(info), NULL, NULL); + if (status != ZX_OK) { + lprofReport("profiling: cannot get basic info about current process: %s\n", + _zx_status_get_string(status)); + return; + } + + /* Give the VMO a name including our process KOID so it's easy to spot. */ + char name[ZX_MAX_NAME_LEN]; + snprintf(name, sizeof(name), "%s.%" PRIu64, sink_name, info.koid); + _zx_object_set_property(output_file, ZX_PROP_NAME, name, strlen(name)); + filename = strdup(name); + + /* We map in the largest possible view into the VMO: one word + * for every possible 32-bit index value. This avoids the need + * to change the mapping when increasing the size of the VMO. + * We can always spare the 32G of address space. + */ + uintptr_t mapping; + status = _zx_vmar_map(_zx_vmar_root_self(), 0, output_file, 0, file_size, + ZX_VM_FLAG_PERM_READ | ZX_VM_FLAG_PERM_WRITE, &mapping); + if (status != ZX_OK) { + lprofReport("profiling: cannot map VMAR: %s\n", + _zx_status_get_string(status)); + return; + } + + /* Initialize the write buffer. */ + write_buffer = (unsigned char *)mapping; + cur_buffer_size = WRITE_BUFFER_SIZE; + cur_pos = 0; + + /* Duplicate the handle since __sanitizer_publish_data consumes it. */ + zx_handle_t handle; + status = _zx_handle_duplicate(output_file, ZX_RIGHT_SAME_RIGHTS, &handle); + if (status != ZX_OK) { + lprofReport("profiling: cannot duplicate VMO handle: %s\n", + _zx_status_get_string(status)); + return; + } + + /* Publish the VMO which contains profile data to the system. */ + __sanitizer_publish_data(sink_name, handle); + + /* Use the dumpfile symbolizer markup element to write the name of VMO. */ + lprofReport("profile: {{{dumpfile:%s:%s}}}\n", sink_name, name); +#endif /* __Fuchsia__ */ /* gcda file, version, stamp checksum. */ write_bytes("adcg", 4); @@ -572,6 +655,7 @@ if (output_file) { write_bytes("\0\0\0\0\0\0\0\0", 8); +#ifndef __Fuchsia__ if (new_file) { fwrite(write_buffer, cur_pos, 1, output_file); free(write_buffer); @@ -584,6 +668,25 @@ fclose(output_file); output_file = NULL; write_buffer = NULL; +#else /* __Fuchsia__ */ + zx_status_t status; + uintptr_t mapping = (uintptr_t)write_buffer; + status = _zx_vmar_unmap(_zx_vmar_root_self(), mapping, cur_buffer_size); + if (status != ZX_OK) { + lprofReport("profiling: failed to unmap VMAR: %s\n", + _zx_status_get_string(status)); + return; + } + + status = _zx_handle_close(output_file); + if (status != ZX_OK) { + lprofReport("profiling: failed to close VMO: %s\n", + _zx_status_get_string(status)); + return; + } + output_file = ZX_HANDLE_INVALID; + write_buffer = NULL; +#endif /* __Fuchsia__ */ } free(filename); @@ -652,5 +755,3 @@ atexit(llvm_writeout_files); } } - -#endif Index: compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c =================================================================== --- compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c +++ compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c @@ -46,17 +46,6 @@ static const char ProfileSinkName[] = "llvm-profile"; -static inline void lprofWrite(const char *fmt, ...) { - char s[256]; - - va_list ap; - va_start(ap, fmt); - int ret = vsnprintf(s, sizeof(s), fmt, ap); - va_end(ap); - - __sanitizer_log_write(s, ret + 1); -} - static uint32_t lprofVMOWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs, uint32_t NumIOVecs) { /* Allocate VMO if it hasn't been created yet. */ @@ -92,7 +81,7 @@ __sanitizer_publish_data(ProfileSinkName, Handle); /* Use the dumpfile symbolizer markup element to write the name of VMO. */ - lprofWrite("LLVM Profile: {{{dumpfile:%s:%s}}}\n", + lproReport("LLVM Profile: {{{dumpfile:%s:%s}}}\n", ProfileSinkName, VmoName); } @@ -129,16 +118,16 @@ static int dump(void) { if (lprofProfileDumped()) { - lprofWrite("Profile data not published: already written.\n"); + lprofReport("Profile data not published: already written.\n"); return 0; } /* Check if there is llvm/runtime version mismatch. */ if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) { - lprofWrite("Runtime and instrumentation version mismatch : " - "expected %d, but got %d\n", - INSTR_PROF_RAW_VERSION, - (int)GET_VERSION(__llvm_profile_get_version())); + lprofReport("Runtime and instrumentation version mismatch : " + "expected %d, but got %d\n", + INSTR_PROF_RAW_VERSION, + (int)GET_VERSION(__llvm_profile_get_version())); return -1; } Index: compiler-rt/lib/profile/InstrProfilingUtil.h =================================================================== --- compiler-rt/lib/profile/InstrProfilingUtil.h +++ compiler-rt/lib/profile/InstrProfilingUtil.h @@ -9,6 +9,7 @@ #ifndef PROFILE_INSTRPROFILINGUTIL_H #define PROFILE_INSTRPROFILINGUTIL_H +#include #include #include @@ -67,4 +68,9 @@ /* Restore previously suspended SIGKILL. */ void lprofRestoreSigKill(); +#ifdef __Fuchsia__ +/* Write a formatted message to the system log. */ +void lprofReport(const char *fmt, ...); +#endif + #endif /* PROFILE_INSTRPROFILINGUTIL_H */ Index: compiler-rt/lib/profile/InstrProfilingUtil.c =================================================================== --- compiler-rt/lib/profile/InstrProfilingUtil.c +++ compiler-rt/lib/profile/InstrProfilingUtil.c @@ -31,6 +31,10 @@ #include #endif +#if defined(__Fuchsia__) +#include +#endif + #include "InstrProfiling.h" #include "InstrProfilingUtil.h" @@ -287,3 +291,16 @@ prctl(PR_SET_PDEATHSIG, SIGKILL); #endif } + +#if defined(__Fuchsia__) +COMPILER_RT_VISIBILITY void lprofReport(const char *fmt, ...) { + char s[256]; + + va_list ap; + va_start(ap, fmt); + int ret = vsnprintf(s, sizeof(s), fmt, ap); + va_end(ap); + + __sanitizer_log_write(s, ret + 1); +} +#endif