aboutsummaryrefslogtreecommitdiffstats
path: root/lib/profile
diff options
context:
space:
mode:
Diffstat (limited to 'lib/profile')
-rw-r--r--lib/profile/InstrProfiling.h17
-rw-r--r--lib/profile/InstrProfilingFile.c11
-rw-r--r--lib/profile/InstrProfilingPlatformFuchsia.c93
-rw-r--r--lib/profile/InstrProfilingRuntime.cpp (renamed from lib/profile/InstrProfilingRuntime.cc)0
-rw-r--r--lib/profile/InstrProfilingUtil.c20
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;