Initialize LTTng tracepoint provider as part of loading libcoreclr.so.
authorBrian Robbins <brianrob@microsoft.com>
Wed, 21 Oct 2015 23:34:42 +0000 (16:34 -0700)
committerBrian Robbins <brianrob@microsoft.com>
Thu, 22 Oct 2015 00:15:05 +0000 (17:15 -0700)
src/pal/inc/pal.h
src/pal/src/misc/miscpalapi.cpp

index 7bddd88..d2d5ed9 100644 (file)
@@ -491,6 +491,26 @@ typedef long time_t;
 typedef DWORD (PALAPI *PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter);
 typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
 
+
+/******************* Tracing Initialization *******************************/
+
+#if defined(__LINUX__)
+
+// Constructor priority is set to 200, which allows for constructors to
+// guarantee that they run before or after this constructor by setting
+// their priority appropriately.
+
+// Priority values must be greater than 100.  The lower the value,
+// the higher the priority.
+static
+void
+__attribute__((__unused__))
+__attribute__((constructor (200)))
+PAL_InitializeTracing(void);
+
+#endif
+
+
 /******************* PAL-Specific Entrypoints *****************************/
 
 PALIMPORT
index 0aeeb89..206a5b7 100644 (file)
@@ -50,6 +50,80 @@ SET_DEFAULT_DEBUG_CHANNEL(MISC);
 static const char RANDOM_DEVICE_NAME[] ="/dev/random";
 static const char URANDOM_DEVICE_NAME[]="/dev/urandom";
 
+
+/*++
+
+Initialization logic for LTTng tracepoint providers.
+
+--*/
+#if defined(__LINUX__)
+
+static const char tpLibName[] = "libcoreclrtraceptprovider.so";
+
+
+/*++
+
+NOTE: PAL_InitializeTracing MUST NOT depend on anything in the PAL itself
+as it is called prior to PAL initialization.
+
+--*/
+static
+void
+PAL_InitializeTracing(void)
+{
+    // Get the path to the currently executing shared object (libcoreclr.so).
+    Dl_info info;
+    int succeeded = dladdr((void *)PAL_InitializeTracing, &info);
+    if(!succeeded)
+    {
+        return;
+    }
+
+    // Copy the path and modify the shared object name to be the tracepoint provider.
+    char tpProvPath[MAX_LONGPATH];
+    int pathLen = strlen(info.dli_fname);
+    int tpLibNameLen = strlen(tpLibName);
+
+    // Find the length of the full path without the shared object name, including the trailing slash.
+    int lastTrailingSlashLen = -1;
+    for(int i=pathLen-1; i>=0; i--)
+    {
+        if(info.dli_fname[i] == '/')
+        {
+            lastTrailingSlashLen = i+1;
+            break;
+        }
+    }
+
+    // Make sure we found the last trailing slash.
+    if(lastTrailingSlashLen == -1)
+    {
+        return;
+    }
+
+    // Make sure that the final path is shorter than MAX_PATH.
+    // +1 ensures that the string can be NULL-terminated.
+    if((lastTrailingSlashLen + tpLibNameLen + 1) > MAX_LONGPATH)
+    {
+        return;
+    }
+
+    // Copy the path without the shared object name.
+    memcpy(&tpProvPath, info.dli_fname, lastTrailingSlashLen);
+
+    // Append the shared object name for the tracepoint provider.
+    memcpy(&tpProvPath[lastTrailingSlashLen], &tpLibName, tpLibNameLen);
+
+    // NULL-terminate the string.
+    tpProvPath[lastTrailingSlashLen + tpLibNameLen] = '\0';
+
+    // Load the tracepoint provider.
+    // It's OK if this fails - that just means that tracing dependencies aren't available.
+    dlopen(tpProvPath, RTLD_NOW | RTLD_GLOBAL);
+}
+
+#endif
+
 /*++
 
 Function :