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