diff options
Diffstat (limited to 'lib/profile')
-rw-r--r-- | lib/profile/InstrProfiling.h | 17 | ||||
-rw-r--r-- | lib/profile/InstrProfilingFile.c | 11 | ||||
-rw-r--r-- | lib/profile/InstrProfilingPlatformFuchsia.c | 93 | ||||
-rw-r--r-- | lib/profile/InstrProfilingRuntime.cpp (renamed from lib/profile/InstrProfilingRuntime.cc) | 0 | ||||
-rw-r--r-- | lib/profile/InstrProfilingUtil.c | 20 |
5 files changed, 89 insertions, 52 deletions
diff --git a/lib/profile/InstrProfiling.h b/lib/profile/InstrProfiling.h index 4d196a89b492..ffc4396169d0 100644 --- a/lib/profile/InstrProfiling.h +++ b/lib/profile/InstrProfiling.h @@ -155,6 +155,10 @@ int __llvm_orderfile_dump(void); * * \c Name is not copied, so it must remain valid. Passing NULL resets the * filename logic to the default behaviour. + * + * Note: There may be multiple copies of the profile runtime (one for each + * instrumented image/DSO). This API only modifies the filename within the + * copy of the runtime available to the calling image. */ void __llvm_profile_set_filename(const char *Name); @@ -173,6 +177,10 @@ void __llvm_profile_set_filename(const char *Name); * with the contents of the profiling file. If EnableMerge is zero, the runtime * may still merge the data if it would have merged for another reason (for * example, because of a %m specifier in the file name). + * + * Note: There may be multiple copies of the profile runtime (one for each + * instrumented image/DSO). This API only modifies the file object within the + * copy of the runtime available to the calling image. */ void __llvm_profile_set_file_object(FILE *File, int EnableMerge); @@ -196,7 +204,12 @@ const char *__llvm_profile_get_path_prefix(); * \brief Return filename (including path) of the profile data. Note that if the * user calls __llvm_profile_set_filename later after invoking this interface, * the actual file name may differ from what is returned here. - * Side-effect: this API call will invoke malloc with dynamic memory allocation. + * Side-effect: this API call will invoke malloc with dynamic memory allocation + * (the returned pointer must be passed to `free` to avoid a leak). + * + * Note: There may be multiple copies of the profile runtime (one for each + * instrumented image/DSO). This API only retrieves the filename from the copy + * of the runtime available to the calling image. */ const char *__llvm_profile_get_filename(); @@ -219,7 +232,7 @@ uint64_t __llvm_profile_get_data_size(const __llvm_profile_data *Begin, void __llvm_profile_set_dumped(); /*! - * This variable is defined in InstrProfilingRuntime.cc as a hidden + * This variable is defined in InstrProfilingRuntime.cpp as a hidden * symbol. Its main purpose is to enable profile runtime user to * bypass runtime initialization code -- if the client code explicitly * define this variable, then InstProfileRuntime.o won't be linked in. diff --git a/lib/profile/InstrProfilingFile.c b/lib/profile/InstrProfilingFile.c index e7996e282894..1b253c3e865e 100644 --- a/lib/profile/InstrProfilingFile.c +++ b/lib/profile/InstrProfilingFile.c @@ -70,7 +70,6 @@ typedef struct lprofFilename { * by runtime. */ unsigned OwnsFilenamePat; const char *ProfilePathPrefix; - const char *Filename; char PidChars[MAX_PID_SIZE]; char Hostname[COMPILER_RT_MAX_HOSTLEN]; unsigned NumPids; @@ -86,8 +85,8 @@ typedef struct lprofFilename { ProfileNameSpecifier PNS; } lprofFilename; -COMPILER_RT_WEAK lprofFilename lprofCurFilename = {0, 0, 0, 0, {0}, - {0}, 0, 0, 0, PNS_unknown}; +static lprofFilename lprofCurFilename = {0, 0, 0, {0}, {0}, + 0, 0, 0, PNS_unknown}; static int ProfileMergeRequested = 0; static int isProfileMergeRequested() { return ProfileMergeRequested; } @@ -387,8 +386,6 @@ static int parseFilenamePattern(const char *FilenamePat, /* Clean up cached prefix and filename. */ if (lprofCurFilename.ProfilePathPrefix) free((void *)lprofCurFilename.ProfilePathPrefix); - if (lprofCurFilename.Filename) - free((void *)lprofCurFilename.Filename); if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) { free((void *)lprofCurFilename.FilenamePat); @@ -602,9 +599,6 @@ const char *__llvm_profile_get_filename(void) { char *FilenameBuf; const char *Filename; - if (lprofCurFilename.Filename) - return lprofCurFilename.Filename; - Length = getCurFilenameLength(); FilenameBuf = (char *)malloc(Length + 1); if (!FilenameBuf) { @@ -615,7 +609,6 @@ const char *__llvm_profile_get_filename(void) { if (!Filename) return "\0"; - lprofCurFilename.Filename = FilenameBuf; return FilenameBuf; } diff --git a/lib/profile/InstrProfilingPlatformFuchsia.c b/lib/profile/InstrProfilingPlatformFuchsia.c index 80beb4145460..2388871a2d54 100644 --- a/lib/profile/InstrProfilingPlatformFuchsia.c +++ b/lib/profile/InstrProfilingPlatformFuchsia.c @@ -27,6 +27,7 @@ #include <zircon/process.h> #include <zircon/sanitizer.h> +#include <zircon/status.h> #include <zircon/syscalls.h> #include "InstrProfiling.h" @@ -57,45 +58,57 @@ static inline void lprofWrite(const char *fmt, ...) { __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. */ - if (__llvm_profile_vmo == ZX_HANDLE_INVALID) { - /* Get information about the current process. */ - zx_info_handle_basic_t Info; - zx_status_t Status = - _zx_object_get_info(_zx_process_self(), ZX_INFO_HANDLE_BASIC, &Info, - sizeof(Info), NULL, NULL); - if (Status != ZX_OK) - return -1; - - /* Create VMO to hold the profile data. */ - Status = _zx_vmo_create(0, ZX_VMO_RESIZABLE, &__llvm_profile_vmo); - if (Status != ZX_OK) - return -1; - - /* Give the VMO a name including our process KOID so it's easy to spot. */ - char VmoName[ZX_MAX_NAME_LEN]; - snprintf(VmoName, sizeof(VmoName), "%s.%" PRIu64, ProfileSinkName, - Info.koid); - _zx_object_set_property(__llvm_profile_vmo, ZX_PROP_NAME, VmoName, - strlen(VmoName)); - - /* Duplicate the handle since __sanitizer_publish_data consumes it. */ - zx_handle_t Handle; - Status = - _zx_handle_duplicate(__llvm_profile_vmo, ZX_RIGHT_SAME_RIGHTS, &Handle); - if (Status != ZX_OK) - return -1; - - /* Publish the VMO which contains profile data to the system. */ - __sanitizer_publish_data(ProfileSinkName, Handle); - - /* Use the dumpfile symbolizer markup element to write the name of VMO. */ - lprofWrite("LLVM Profile: {{{dumpfile:%s:%s}}}\n", - ProfileSinkName, VmoName); +static void createVMO() { + /* Don't create VMO if it has been alread created. */ + if (__llvm_profile_vmo != ZX_HANDLE_INVALID) + return; + + /* Get information about the current process. */ + zx_info_handle_basic_t Info; + zx_status_t Status = + _zx_object_get_info(_zx_process_self(), ZX_INFO_HANDLE_BASIC, &Info, + sizeof(Info), NULL, NULL); + if (Status != ZX_OK) { + lprofWrite("LLVM Profile: cannot get info about current process: %s\n", + _zx_status_get_string(Status)); + return; } + /* Create VMO to hold the profile data. */ + Status = _zx_vmo_create(0, ZX_VMO_RESIZABLE, &__llvm_profile_vmo); + if (Status != ZX_OK) { + lprofWrite("LLVM Profile: cannot create VMO: %s\n", + _zx_status_get_string(Status)); + return; + } + + /* Give the VMO a name including our process KOID so it's easy to spot. */ + char VmoName[ZX_MAX_NAME_LEN]; + snprintf(VmoName, sizeof(VmoName), "%s.%" PRIu64, ProfileSinkName, Info.koid); + _zx_object_set_property(__llvm_profile_vmo, ZX_PROP_NAME, VmoName, + strlen(VmoName)); + + /* Duplicate the handle since __sanitizer_publish_data consumes it. */ + zx_handle_t Handle; + Status = + _zx_handle_duplicate(__llvm_profile_vmo, ZX_RIGHT_SAME_RIGHTS, &Handle); + if (Status != ZX_OK) { + lprofWrite("LLVM Profile: cannot duplicate VMO handle: %s\n", + _zx_status_get_string(Status)); + _zx_handle_close(__llvm_profile_vmo); + __llvm_profile_vmo = ZX_HANDLE_INVALID; + return; + } + + /* Publish the VMO which contains profile data to the system. */ + __sanitizer_publish_data(ProfileSinkName, Handle); + + /* Use the dumpfile symbolizer markup element to write the name of VMO. */ + lprofWrite("LLVM Profile: {{{dumpfile:%s:%s}}}\n", ProfileSinkName, VmoName); +} + +static uint32_t lprofVMOWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs, + uint32_t NumIOVecs) { /* Compute the total length of data to be written. */ size_t Length = 0; for (uint32_t I = 0; I < NumIOVecs; I++) @@ -129,13 +142,13 @@ static void initVMOWriter(ProfDataWriter *This) { static int dump(void) { if (lprofProfileDumped()) { - lprofWrite("Profile data not published: already written.\n"); + lprofWrite("LLVM 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 : " + lprofWrite("LLVM Profile: runtime and instrumentation version mismatch: " "expected %d, but got %d\n", INSTR_PROF_RAW_VERSION, (int)GET_VERSION(__llvm_profile_get_version())); @@ -164,7 +177,7 @@ static void dumpWithoutReturn(void) { dump(); } * InstrProfilingRuntime.o if it is linked in. */ COMPILER_RT_VISIBILITY -void __llvm_profile_initialize_file(void) {} +void __llvm_profile_initialize_file(void) { createVMO(); } COMPILER_RT_VISIBILITY int __llvm_profile_register_write_file_atexit(void) { diff --git a/lib/profile/InstrProfilingRuntime.cc b/lib/profile/InstrProfilingRuntime.cpp index 679186ef8309..679186ef8309 100644 --- a/lib/profile/InstrProfilingRuntime.cc +++ b/lib/profile/InstrProfilingRuntime.cpp diff --git a/lib/profile/InstrProfilingUtil.c b/lib/profile/InstrProfilingUtil.c index 02d100792db8..13301f341fc5 100644 --- a/lib/profile/InstrProfilingUtil.c +++ b/lib/profile/InstrProfilingUtil.c @@ -12,6 +12,7 @@ #include <windows.h> #include "WindowsMMap.h" #else +#include <sys/file.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -39,8 +40,25 @@ COMPILER_RT_WEAK unsigned lprofDirMode = 0755; COMPILER_RT_VISIBILITY void __llvm_profile_recursive_mkdir(char *path) { int i; + int start = 1; + +#if defined(__ANDROID__) && defined(__ANDROID_API__) && \ + defined(__ANDROID_API_FUTURE__) && \ + __ANDROID_API__ == __ANDROID_API_FUTURE__ + // Avoid spammy selinux denial messages in Android by not attempting to + // create directories in GCOV_PREFIX. These denials occur when creating (or + // even attempting to stat()) top-level directories like "/data". + // + // Do so by ignoring ${GCOV_PREFIX} when invoking mkdir(). + const char *gcov_prefix = getenv("GCOV_PREFIX"); + if (gcov_prefix != NULL) { + const int gcov_prefix_len = strlen(gcov_prefix); + if (strncmp(path, gcov_prefix, gcov_prefix_len) == 0) + start = gcov_prefix_len; + } +#endif - for (i = 1; path[i] != '\0'; ++i) { + for (i = start; path[i] != '\0'; ++i) { char save = path[i]; if (!IS_DIR_SEPARATOR(path[i])) continue; |