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