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