summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/profile/InstrProfilingFile.c
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2014-05-17 01:27:30 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2014-05-17 01:27:30 +0000
commit55e4d66f0c427d916c6cc66d18b54be2e87aa847 (patch)
treeb913efce7e8c3eb551c11632bd6dab42bd0504c6 /compiler-rt/lib/profile/InstrProfilingFile.c
parentb0869036c1143d53bb5b585ce06258463e7de1b2 (diff)
downloadbcm5719-llvm-55e4d66f0c427d916c6cc66d18b54be2e87aa847.tar.gz
bcm5719-llvm-55e4d66f0c427d916c6cc66d18b54be2e87aa847.zip
InstrProf: Support profiling dlopen'd shared libraries
Shared objects are hard. After this commit, we do the right thing when profiling two separate shared objects that have been dlopen'd with `RTLD_LOCAL`, when the main executable is *not* being profiled. This mainly simplifies the writer logic. - At initialization, determine the output filename and truncate the file. Depending on whether shared objects can see each other, this may happen multiple times. - At exit, each executable writes its own profile in append mode. <rdar://problem/16918688> llvm-svn: 209053
Diffstat (limited to 'compiler-rt/lib/profile/InstrProfilingFile.c')
-rw-r--r--compiler-rt/lib/profile/InstrProfilingFile.c166
1 files changed, 91 insertions, 75 deletions
diff --git a/compiler-rt/lib/profile/InstrProfilingFile.c b/compiler-rt/lib/profile/InstrProfilingFile.c
index 5ed32d56267..779a68225c3 100644
--- a/compiler-rt/lib/profile/InstrProfilingFile.c
+++ b/compiler-rt/lib/profile/InstrProfilingFile.c
@@ -53,75 +53,60 @@ static int writeFile(FILE *File) {
return 0;
}
-typedef struct __llvm_profile_writer {
- struct __llvm_profile_writer *Next;
- int (*Data)(FILE *);
-} __llvm_profile_writer;
-
-__attribute__((weak)) __llvm_profile_writer *__llvm_profile_HeadWriter = NULL;
-static __llvm_profile_writer Writer = {NULL, writeFile};
-
-__attribute__((visibility("hidden")))
-void __llvm_profile_register_write_file(void) {
- static int HasBeenRegistered = 0;
-
- if (HasBeenRegistered)
- return;
-
- HasBeenRegistered = 1;
- Writer.Next = __llvm_profile_HeadWriter;
- __llvm_profile_HeadWriter = &Writer;
-}
-
static int writeFileWithName(const char *OutputName) {
int RetVal;
FILE *OutputFile;
if (!OutputName || !OutputName[0])
return -1;
- OutputFile = fopen(OutputName, "w");
+
+ /* Append to the file to support profiling multiple shared objects. */
+ OutputFile = fopen(OutputName, "a");
if (!OutputFile)
return -1;
- __llvm_profile_writer *Writer = __llvm_profile_HeadWriter;
- if (Writer)
- for (; Writer; Writer = Writer->Next) {
- RetVal = Writer->Data(OutputFile);
- if (RetVal != 0)
- break;
- }
- else
- // Default to calling this executable's writeFile.
- RetVal = writeFile(OutputFile);
+ RetVal = writeFile(OutputFile);
fclose(OutputFile);
return RetVal;
}
+__attribute__((weak)) int __llvm_profile_OwnsFilename = 0;
__attribute__((weak)) const char *__llvm_profile_CurrentFilename = NULL;
-__attribute__((weak)) void __llvm_profile_set_filename(const char *Filename) {
+
+static void setFilename(const char *Filename, int OwnsFilename) {
+ if (__llvm_profile_OwnsFilename)
+ free((char *)__llvm_profile_CurrentFilename);
+
__llvm_profile_CurrentFilename = Filename;
+ __llvm_profile_OwnsFilename = OwnsFilename;
}
-int getpid(void);
-__attribute__((weak)) int __llvm_profile_write_file(void) {
- char *AllocatedFilename = NULL;
- int I, J;
- int RetVal;
+static void truncateCurrentFile(void) {
+ const char *Filename = __llvm_profile_CurrentFilename;
+ if (!Filename || !Filename[0])
+ return;
-#define MAX_PID_SIZE 16
- char PidChars[MAX_PID_SIZE] = { 0 };
- int PidLength = 0;
- int NumPids = 0;
+ /* Truncate the file. Later we'll reopen and append. */
+ FILE *File = fopen(Filename, "w");
+ if (!File)
+ return;
+ fclose(File);
+}
- /* Get the filename. */
- const char *Filename = __llvm_profile_CurrentFilename;
-#define UPDATE_FILENAME(NextFilename) \
- if (!Filename || !Filename[0]) Filename = NextFilename
- UPDATE_FILENAME(getenv("LLVM_PROFILE_FILE"));
- UPDATE_FILENAME("default.profraw");
-#undef UPDATE_FILENAME
+static void setDefaultFilename(void) { setFilename("default.profraw", 0); }
+
+int getpid(void);
+static int setFilenameFromEnvironment(void) {
+ const char *Filename = getenv("LLVM_PROFILE_FILE");
+ if (!Filename || !Filename[0])
+ return -1;
/* Check the filename for "%p", which indicates a pid-substitution. */
+#define MAX_PID_SIZE 16
+ char PidChars[MAX_PID_SIZE] = {0};
+ int NumPids = 0;
+ int PidLength = 0;
+ int I;
for (I = 0; Filename[I]; ++I)
if (Filename[I] == '%' && Filename[++I] == 'p')
if (!NumPids++) {
@@ -129,43 +114,74 @@ __attribute__((weak)) int __llvm_profile_write_file(void) {
if (PidLength <= 0)
return -1;
}
- if (NumPids) {
- /* Allocate enough space for the substituted filename. */
- AllocatedFilename = (char*)malloc(I + NumPids*(PidLength - 2) + 1);
- if (!AllocatedFilename)
- return -1;
-
- /* Construct the new filename. */
- for (I = 0, J = 0; Filename[I]; ++I)
- if (Filename[I] == '%') {
- if (Filename[++I] == 'p') {
- memcpy(AllocatedFilename + J, PidChars, PidLength);
- J += PidLength;
- }
- /* Drop any unknown substitutions. */
- } else
- AllocatedFilename[J++] = Filename[I];
- AllocatedFilename[J] = 0;
-
- /* Actually use the computed name. */
- Filename = AllocatedFilename;
+ if (!NumPids) {
+ setFilename(Filename, 0);
+ return 0;
}
- /* Write the file. */
- RetVal = writeFileWithName(Filename);
+ /* Allocate enough space for the substituted filename. */
+ char *Allocated = (char*)malloc(I + NumPids*(PidLength - 2) + 1);
+ if (!Allocated)
+ return -1;
- /* Free the filename. */
- if (AllocatedFilename)
- free(AllocatedFilename);
+ /* Construct the new filename. */
+ int J;
+ for (I = 0, J = 0; Filename[I]; ++I)
+ if (Filename[I] == '%') {
+ if (Filename[++I] == 'p') {
+ memcpy(Allocated + J, PidChars, PidLength);
+ J += PidLength;
+ }
+ /* Drop any unknown substitutions. */
+ } else
+ Allocated[J++] = Filename[I];
+ Allocated[J] = 0;
- return RetVal;
+ /* Use the computed name. */
+ setFilename(Allocated, 1);
+ return 0;
+}
+
+static void setFilenameAutomatically(void) {
+ if (!setFilenameFromEnvironment())
+ return;
+
+ setDefaultFilename();
+}
+
+__attribute__((visibility("hidden")))
+void __llvm_profile_initialize_file(void) {
+ /* Check if the filename has been initialized. */
+ if (__llvm_profile_CurrentFilename)
+ return;
+
+ /* Detect the filename and truncate. */
+ setFilenameAutomatically();
+ truncateCurrentFile();
+}
+
+__attribute__((visibility("hidden")))
+void __llvm_profile_set_filename(const char *Filename) {
+ setFilename(Filename, 0);
+ truncateCurrentFile();
+}
+
+__attribute__((visibility("hidden")))
+int __llvm_profile_write_file(void) {
+ /* Check the filename. */
+ if (!__llvm_profile_CurrentFilename)
+ return -1;
+
+ /* Write the file. */
+ return writeFileWithName(__llvm_profile_CurrentFilename);
}
static void writeFileWithoutReturn(void) {
__llvm_profile_write_file();
}
-__attribute__((weak)) int __llvm_profile_register_write_file_atexit(void) {
+__attribute__((visibility("hidden")))
+int __llvm_profile_register_write_file_atexit(void) {
static int HasBeenRegistered = 0;
if (HasBeenRegistered)
OpenPOWER on IntegriCloud