vscode: Add configurations to run the executables under the debugger
[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 <popt.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13
14 #if HAS_CALLSITES
15 #include "callsites.h"
16 #endif
17
18 void exec_callsite(void);
19 void exec_callsite(void)
20 {
21 #if HAS_CALLSITES
22 call_tracepoint();
23 #endif
24 }
25
26 static void print_list(void)
27 {
28 fprintf(stderr, "Test list (-t X):\n");
29 fprintf(stderr,
30 "\t0: dlopen() all libraries pass in arguments and execute "
31 "the callsite.\n");
32 fprintf(stderr,
33 "\t1: simulate the upgrade of a probe provider using dlopen() and dlclose(). \n");
34 fprintf(stderr,
35 "\t2: simulate the upgrade of a library containing the callsites using dlopen() and dlclose(). \n");
36 }
37
38 #if HAS_CALLSITES
39 static int dl_open_all(int nb_libraries, char **libraries)
40 {
41 int i, ret = 0;
42 void **handles;
43
44 handles = malloc(nb_libraries * sizeof(void *));
45 if (!handles) {
46 ret = -1;
47 goto error;
48 }
49
50 /* Iterate over the libs to dlopen and save the handles. */
51 for (i = 0; i < nb_libraries; i++) {
52 handles[i] = dlopen(libraries[i], RTLD_NOW);
53 if (!handles[i]) {
54 ret = -1;
55 goto error;
56 }
57 }
58
59 exec_callsite();
60 error:
61 free(handles);
62 return ret;
63 }
64
65 /*
66 * Takes 2 paths to libraries, dlopen() the first, trace, dlopen() the second,
67 * and dlclose the first to simulate the upgrade of a library.
68 */
69 static 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 int upgrade_callsite(int nb_libraries, char **libraries)
108 {
109 int ret = 0;
110 void *handles[2];
111 void (*fct_ptr[2])(void);
112
113 if (nb_libraries != 2) {
114 ret = -1;
115 goto error;
116 }
117
118 /* Load the probes in the first library. */
119 handles[0] = dlopen(libraries[0], RTLD_NOW);
120 if (!handles[0]) {
121 ret = -1;
122 goto error;
123 }
124
125 /*
126 * Get the pointer to the old function containing the callsite and call it.
127 */
128 fct_ptr[0] = dlsym(handles[0], "call_tracepoint");
129 if (!fct_ptr[0]) {
130 ret = -1;
131 goto error;
132 }
133 fct_ptr[0]();
134
135 /* Load the new callsite library. */
136 handles[1] = dlopen(libraries[1], RTLD_NOW);
137 if (!handles[1]) {
138 ret = -1;
139 goto error;
140 }
141
142 /*
143 * Get the pointer to the new function containing the callsite and call it.
144 */
145 fct_ptr[1] = dlsym(handles[1], "call_tracepoint");
146 if (!fct_ptr[1]) {
147 ret = -1;
148 goto error;
149 }
150 fct_ptr[1]();
151
152 /* Unload the old callsite library. */
153 ret = dlclose(handles[0]);
154 if (ret) {
155 goto error;
156 }
157
158 /* Call the function containing the callsite in the new library. */
159 fct_ptr[1]();
160
161 ret = dlclose(handles[1]);
162 if (ret) {
163 goto error;
164 }
165
166 error:
167 return ret;
168 }
169 #endif /* !HAS_CALLSITES */
170
171 int main(int argc, const char **argv)
172 {
173 int c, ret = 0, test = -1, nb_libraries = 0;
174 char **libraries = NULL;
175 poptContext optCon;
176 struct poptOption optionsTable[] = {
177 { "test", 't', POPT_ARG_INT, &test, 0, "Test to run", NULL },
178 { "list", 'l', 0, 0, 'l', "List of tests (-t X)", NULL },
179 POPT_AUTOHELP{ NULL, 0, 0, NULL, 0, NULL, NULL }
180 };
181
182 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
183 if (argc < 2) {
184 poptPrintUsage(optCon, stderr, 0);
185 ret = -1;
186 goto error;
187 }
188
189 while ((c = poptGetNextOpt(optCon)) >= 0) {
190 switch (c) {
191 case 'l':
192 print_list();
193 goto error;
194 }
195 }
196
197 /*
198 * Populate the libraries array with the arguments passed to the process.
199 */
200 while (poptPeekArg(optCon) != NULL) {
201 char **realloced_libraries = NULL;
202
203 nb_libraries++;
204 realloced_libraries = realloc(libraries, nb_libraries * sizeof(char *));
205 if (!realloced_libraries) {
206 ret = -1;
207 goto error;
208 }
209 libraries = realloced_libraries;
210 libraries[nb_libraries - 1] = (char *) poptGetArg(optCon);
211 }
212
213 switch (test) {
214 case 0:
215 #if HAS_CALLSITES
216 ret = dl_open_all(nb_libraries, libraries);
217 #else
218 fprintf(stderr,
219 "Test not implemented for configuration "
220 "(HAS_CALLSITES=%d)\n",
221 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,
229 "Test not implemented for configuration "
230 "(HAS_CALLSITES=%d)\n",
231 HAS_CALLSITES == 1);
232 #endif
233 break;
234 case 2:
235 #if !HAS_CALLSITES
236 ret = upgrade_callsite(nb_libraries, libraries);
237 #else
238 fprintf(stderr,
239 "Test not implemented for configuration "
240 "(HAS_CALLSITES=%d)\n",
241 HAS_CALLSITES == 1);
242 #endif
243 break;
244 default:
245 fprintf(stderr, "Test %d not implemented\n", test);
246 ret = -1;
247 break;
248 }
249 error:
250 free(libraries);
251 poptFreeContext(optCon);
252 return ret;
253 }
This page took 0.0349739999999999 seconds and 5 git commands to generate.