InstrProf: Fix shared object profiling

Change the API of the instrumented profiling library to work with shared
objects.

  - Most things are now declared hidden, so that each executable gets
    its own copy.

  - Initialization hooks up a linked list of writers.

  - The raw format with shared objects that are profiled consists of a
    concatenated series of profiles.  llvm-profdata knows how to deal
    with that since r208938.

<rdar://problem/16918688>

llvm-svn: 208940
diff --git a/compiler-rt/lib/profile/InstrProfilingFile.c b/compiler-rt/lib/profile/InstrProfilingFile.c
index 2c40ca5..5ed32d5 100644
--- a/compiler-rt/lib/profile/InstrProfilingFile.c
+++ b/compiler-rt/lib/profile/InstrProfilingFile.c
@@ -25,6 +25,10 @@
   const uint64_t DataSize = DataEnd - DataBegin;
   const uint64_t CountersSize = CountersEnd - CountersBegin;
   const uint64_t NamesSize = NamesEnd - NamesBegin;
+  const uint64_t Padding = sizeof(uint64_t) - NamesSize % sizeof(uint64_t);
+
+  /* Enough zeroes for padding. */
+  const char Zeroes[sizeof(uint64_t)] = {0};
 
   /* Create the header. */
   uint64_t Header[PROFILE_HEADER_SIZE];
@@ -43,9 +47,30 @@
   CHECK_fwrite(DataBegin,     sizeof(__llvm_profile_data), DataSize, File);
   CHECK_fwrite(CountersBegin, sizeof(uint64_t), CountersSize, File);
   CHECK_fwrite(NamesBegin,    sizeof(char), NamesSize, File);
+  CHECK_fwrite(Zeroes,        sizeof(char), Padding, File);
 #undef CHECK_fwrite
 
-   return 0;
+  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) {
@@ -57,19 +82,28 @@
   if (!OutputFile)
     return -1;
 
-  RetVal = writeFile(OutputFile);
+  __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);
 
   fclose(OutputFile);
   return RetVal;
 }
 
-static const char *CurrentFilename = NULL;
-void __llvm_profile_set_filename(const char *Filename) {
-  CurrentFilename = Filename;
+__attribute__((weak)) const char *__llvm_profile_CurrentFilename = NULL;
+__attribute__((weak)) void __llvm_profile_set_filename(const char *Filename) {
+  __llvm_profile_CurrentFilename = Filename;
 }
 
 int getpid(void);
-int __llvm_profile_write_file(void) {
+__attribute__((weak)) int __llvm_profile_write_file(void) {
   char *AllocatedFilename = NULL;
   int I, J;
   int RetVal;
@@ -80,7 +114,7 @@
   int NumPids = 0;
 
   /* Get the filename. */
-  const char *Filename = CurrentFilename;
+  const char *Filename = __llvm_profile_CurrentFilename;
 #define UPDATE_FILENAME(NextFilename) \
   if (!Filename || !Filename[0]) Filename = NextFilename
   UPDATE_FILENAME(getenv("LLVM_PROFILE_FILE"));
@@ -131,7 +165,7 @@
   __llvm_profile_write_file();
 }
 
-int __llvm_profile_register_write_file_atexit(void) {
+__attribute__((weak)) int __llvm_profile_register_write_file_atexit(void) {
   static int HasBeenRegistered = 0;
 
   if (HasBeenRegistered)