218b1196be438ce2d6402e4891605db8a841a0b8
[lttng-tools.git] / tests / regression / ust / multi-lib / multi-lib-test.c
1 /*
2 * Copyright (C) 2018 Francis Deslauriers <francis.deslauriers@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <dlfcn.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <popt.h>
13
14 #if HAS_CALLSITES
15 #include "callsites.h"
16 #endif
17
18 void exec_callsite();
19 void exec_callsite()
20 {
21 #if HAS_CALLSITES
22 call_tracepoint();
23 #endif
24 }
25
26 static
27 void print_list(void)
28 {
29 fprintf(stderr, "Test list (-t X):\n");
30 fprintf(stderr, "\t0: dlopen() all libraries pass in arguments and execute "
31 "the callsite.\n");
32 fprintf(stderr, "\t1: simulate the upgrade of a probe provider using dlopen() and dlclose(). \n");
33 fprintf(stderr, "\t2: simulate the upgrade of a library containing the callsites using dlopen() and dlclose(). \n");
34 }
35
36 #if HAS_CALLSITES
37 static
38 int dl_open_all(int nb_libraries, char **libraries)
39 {
40 int i, ret = 0;
41 void **handles;
42
43 handles = malloc(nb_libraries * sizeof(void *));
44 if (!handles) {
45 ret = -1;
46 goto error;
47 }
48
49 /* Iterate over the libs to dlopen and save the handles. */
50 for (i = 0; i < nb_libraries; i++) {
51 handles[i] = dlopen(libraries[i], RTLD_NOW);
52 if (!handles[i]) {
53 ret = -1;
54 goto error;
55 }
56 }
57
58 exec_callsite();
59 error:
60 free(handles);
61 return ret;
62 }
63
64 /*
65 * Takes 2 paths to libraries, dlopen() the first, trace, dlopen() the second,
66 * and dlclose the first to simulate the upgrade of a library.
67 */
68 static
69 int upgrade_lib(int nb_libraries, char **libraries)
70 {
71 int i, ret = 0;
72 void *handles[2];
73
74 if (nb_libraries != 2) {
75 ret = -1;
76 goto error;
77 }
78
79 /* Iterate over the libs to dlopen and save the handles. */
80 for (i = 0; i < nb_libraries; i++) {
81 handles[i] = dlopen(libraries[i], RTLD_NOW);
82 if (!handles[i]) {
83 ret = -1;
84 goto error;
85 }
86
87 exec_callsite();
88 }
89
90 ret = dlclose(handles[0]);
91 if (ret) {
92 goto error;
93 }
94
95 exec_callsite();
96
97 error:
98 return ret;
99 }
100 #endif /* HAS_CALLSITES */
101
102 #if !HAS_CALLSITES
103 /*
104 * Simulate the upgrade of a library containing a callsite.
105 * Receives two libraries containing callsites for the same tracepoint.
106 */
107 static
108 int upgrade_callsite(int nb_libraries, char **libraries)
109 {
110 int ret = 0;
111 void *handles[2];
112 void (*fct_ptr[2])(void);
113
114 if (nb_libraries != 2) {
115 ret = -1;
116 goto error;
117 }
118
119 /* Load the probes in the first library. */
120 handles[0] = dlopen(libraries[0], RTLD_NOW);
121 if (!handles[0]) {
122 ret = -1;
123 goto error;
124 }
125
126 /*
127 * Get the pointer to the old function containing the callsite and call it.
128 */
129 fct_ptr[0] = dlsym(handles[0], "call_tracepoint");
130 if (!fct_ptr[0]) {
131 ret = -1;
132 goto error;
133 }
134 fct_ptr[0]();
135
136 /* Load the new callsite library. */
137 handles[1] = dlopen(libraries[1], RTLD_NOW);
138 if (!handles[1]) {
139 ret = -1;
140 goto error;
141 }
142
143 /*
144 * Get the pointer to the new function containing the callsite and call it.
145 */
146 fct_ptr[1] = dlsym(handles[1], "call_tracepoint");
147 if (!fct_ptr[1]) {
148 ret = -1;
149 goto error;
150 }
151 fct_ptr[1]();
152
153 /* Unload the old callsite library. */
154 ret = dlclose(handles[0]);
155 if (ret) {
156 goto error;
157 }
158
159 /* Call the function containing the callsite in the new library. */
160 fct_ptr[1]();
161
162 ret = dlclose(handles[1]);
163 if (ret) {
164 goto error;
165 }
166
167 error:
168 return ret;
169 }
170 #endif /* !HAS_CALLSITES */
171
172 int main(int argc, const char **argv)
173 {
174 int c, ret = 0, test = -1, nb_libraries = 0;
175 char **libraries = NULL;
176 poptContext optCon;
177 struct poptOption optionsTable[] = {
178 { "test", 't', POPT_ARG_INT, &test, 0, "Test to run", NULL },
179 { "list", 'l', 0, 0, 'l', "List of tests (-t X)", NULL },
180 POPT_AUTOHELP
181 { NULL, 0, 0, NULL, 0 }
182 };
183
184 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
185 if (argc < 2) {
186 poptPrintUsage(optCon, stderr, 0);
187 ret = -1;
188 goto error;
189 }
190
191 while ((c = poptGetNextOpt(optCon)) >= 0) {
192 switch(c) {
193 case 'l':
194 print_list();
195 goto error;
196 }
197 }
198
199 /*
200 * Populate the libraries array with the arguments passed to the process.
201 */
202 while (poptPeekArg(optCon) != NULL) {
203 char **realloced_libraries = NULL;
204
205 nb_libraries++;
206 realloced_libraries = realloc(libraries, nb_libraries * sizeof(char *));
207 if (!realloced_libraries) {
208 ret = -1;
209 goto error;
210 }
211 libraries = realloced_libraries;
212 libraries[nb_libraries - 1] = (char *) poptGetArg(optCon);
213 }
214
215 switch(test) {
216 case 0:
217 #if HAS_CALLSITES
218 ret = dl_open_all(nb_libraries, libraries);
219 #else
220 fprintf(stderr, "Test not implemented for configuration "
221 "(HAS_CALLSITES=%d)\n", HAS_CALLSITES == 1);
222 #endif
223 break;
224 case 1:
225 #if HAS_CALLSITES
226 ret = upgrade_lib(nb_libraries, libraries);
227 #else
228 fprintf(stderr, "Test not implemented for configuration "
229 "(HAS_CALLSITES=%d)\n", HAS_CALLSITES == 1);
230 #endif
231 break;
232 case 2:
233 #if !HAS_CALLSITES
234 ret = upgrade_callsite(nb_libraries, libraries);
235 #else
236 fprintf(stderr, "Test not implemented for configuration "
237 "(HAS_CALLSITES=%d)\n", HAS_CALLSITES == 1);
238 #endif
239 break;
240 default:
241 fprintf(stderr, "Test %d not implemented\n", test);
242 ret = -1;
243 break;
244 }
245 error:
246 free(libraries);
247 poptFreeContext(optCon);
248 return ret;
249 }
This page took 0.047553 seconds and 3 git commands to generate.