1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /*++ |
6 | |
7 | Module Name: |
8 | |
9 | tracepointprovider.cpp |
10 | |
11 | Abstract: |
12 | |
13 | Trace point provider support |
14 | |
15 | Revision History: |
16 | |
17 | --*/ |
18 | |
19 | #include "pal/palinternal.h" |
20 | #include "pal/dbgmsg.h" |
21 | #include "pal/file.h" |
22 | #include "pal/process.h" |
23 | #include "pal/module.h" |
24 | #include "pal/malloc.hpp" |
25 | #include "pal/stackstring.hpp" |
26 | |
27 | #include <errno.h> |
28 | #include <unistd.h> |
29 | #include <pthread.h> |
30 | #include <dlfcn.h> |
31 | |
32 | SET_DEFAULT_DEBUG_CHANNEL(MISC); |
33 | |
34 | /*++ |
35 | |
36 | Initialization logic for LTTng tracepoint providers. |
37 | |
38 | --*/ |
39 | #if defined(__linux__) |
40 | |
41 | static const char tpLibName[] = "libcoreclrtraceptprovider.so" ; |
42 | |
43 | |
44 | /*++ |
45 | |
46 | NOTE: PAL_InitializeTracing MUST NOT depend on anything in the PAL itself |
47 | as it is called prior to PAL initialization. |
48 | |
49 | Constructor priority is set to 200, which allows for constructors to |
50 | guarantee that they run before or after this constructor by setting |
51 | their priority appropriately. |
52 | |
53 | Priority values must be greater than 100. The lower the value, |
54 | the higher the priority. |
55 | |
56 | --*/ |
57 | __attribute__((__unused__)) |
58 | __attribute__((constructor (200))) |
59 | static void |
60 | PAL_InitializeTracing(void) |
61 | { |
62 | // Get the path to the currently executing shared object (libcoreclr.so). |
63 | Dl_info info; |
64 | int succeeded = dladdr((void *)PAL_InitializeTracing, &info); |
65 | if(!succeeded) |
66 | { |
67 | return; |
68 | } |
69 | |
70 | // Copy the path and modify the shared object name to be the tracepoint provider. |
71 | PathCharString tpProvPath; |
72 | int pathLen = strlen(info.dli_fname); |
73 | |
74 | // Find the length of the full path without the shared object name, including the trailing slash. |
75 | int lastTrailingSlashLen = -1; |
76 | for(int i=pathLen-1; i>=0; i--) |
77 | { |
78 | if(info.dli_fname[i] == '/') |
79 | { |
80 | lastTrailingSlashLen = i+1; |
81 | break; |
82 | } |
83 | } |
84 | |
85 | // Make sure we found the last trailing slash. |
86 | if(lastTrailingSlashLen == -1) |
87 | { |
88 | return; |
89 | } |
90 | |
91 | SIZE_T tpLibNameLen = strlen(tpLibName); |
92 | |
93 | if( !tpProvPath.Reserve(tpLibNameLen + lastTrailingSlashLen) || |
94 | // Copy the path without the shared object name. |
95 | !tpProvPath.Append(info.dli_fname, lastTrailingSlashLen) || |
96 | // Append the shared object name for the tracepoint provider. |
97 | !tpProvPath.Append(tpLibName, tpLibNameLen)) |
98 | { |
99 | return; |
100 | } |
101 | |
102 | |
103 | |
104 | // Load the tracepoint provider. |
105 | // It's OK if this fails - that just means that tracing dependencies aren't available. |
106 | dlopen(tpProvPath, RTLD_NOW | RTLD_GLOBAL); |
107 | } |
108 | |
109 | #endif |
110 | |