X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=tests%2Fregression%2Fust%2Fmulti-lib%2Fmulti-lib-test.c;fp=tests%2Fregression%2Fust%2Fmulti-lib%2Fmulti-lib-test.c;h=e145aa21aeae49e8310dc498c40e301499b88126;hp=0000000000000000000000000000000000000000;hb=3f7f208a0150d93363cbf7755e890a9839114ab5;hpb=c54b437e412758d71ee7cb61d1a60085009f3f90 diff --git a/tests/regression/ust/multi-lib/multi-lib-test.c b/tests/regression/ust/multi-lib/multi-lib-test.c new file mode 100644 index 000000000..e145aa21a --- /dev/null +++ b/tests/regression/ust/multi-lib/multi-lib-test.c @@ -0,0 +1,247 @@ +/* + * Copyright (C) - 2018 Francis Deslauriers + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#if HAS_CALLSITES +#include "callsites.h" +#endif + +void exec_callsite() +{ +#if HAS_CALLSITES + call_tracepoint(); +#endif +} + +void print_list(void) +{ + fprintf(stderr, "Test list (-t X):\n"); + fprintf(stderr, "\t0: dlopen() all libraries pass in arguments and execute " + "the callsite.\n"); + fprintf(stderr, "\t1: simulate the upgrade of a probe provider using dlopen() and dlclose(). \n"); + fprintf(stderr, "\t2: simulate the upgrade of a library containing the callsites using dlopen() and dlclose(). \n"); +} + +int dl_open_all(int nb_libraries, char **libraries) +{ + int i, ret = 0; + void **handles; + + handles = malloc(nb_libraries * sizeof(void *)); + if (!handles) { + ret = -1; + goto error; + } + + /* Iterate over the libs to dlopen and save the handles. */ + for (i = 0; i < nb_libraries; i++) { + handles[i] = dlopen(libraries[i], RTLD_NOW); + if (!handles[i]) { + ret = -1; + goto error; + } + } + + exec_callsite(); +error: + free(handles); + return ret; +} + +/* + * Takes 2 paths to libraries, dlopen() the first, trace, dlopen() the second, + * and dlclose the first to simulate the upgrade of a library. + */ +int upgrade_lib(int nb_libraries, char **libraries) +{ + int i, ret = 0; + void *handles[2]; + + if (nb_libraries != 2) { + ret = -1; + goto error; + } + + /* Iterate over the libs to dlopen and save the handles. */ + for (i = 0; i < nb_libraries; i++) { + handles[i] = dlopen(libraries[i], RTLD_NOW); + if (!handles[i]) { + ret = -1; + goto error; + } + + exec_callsite(); + } + + ret = dlclose(handles[0]); + if (ret) { + goto error; + } + + exec_callsite(); + +error: + return ret; +} + +/* + * Simulate the upgrade of a library containing a callsite. + * Receives two libraries containing callsites for the same tracepoint. + */ +int upgrade_callsite(int nb_libraries, char **libraries) +{ + int ret = 0; + void *handles[2]; + void (*fct_ptr[2])(void); + + if (nb_libraries != 2) { + ret = -1; + goto error; + } + + /* Load the probes in the first library. */ + handles[0] = dlopen(libraries[0], RTLD_NOW); + if (!handles[0]) { + ret = -1; + goto error; + } + + /* + * Get the pointer to the old function containing the callsite and call it. + */ + fct_ptr[0] = dlsym(handles[0], "call_tracepoint"); + if (!fct_ptr[0]) { + ret = -1; + goto error; + } + fct_ptr[0](); + + /* Load the new callsite library. */ + handles[1] = dlopen(libraries[1], RTLD_NOW); + if (!handles[1]) { + ret = -1; + goto error; + } + + /* + * Get the pointer to the new function containing the callsite and call it. + */ + fct_ptr[1] = dlsym(handles[1], "call_tracepoint"); + if (!fct_ptr[1]) { + ret = -1; + goto error; + } + fct_ptr[1](); + + /* Unload the old callsite library. */ + ret = dlclose(handles[0]); + if (ret) { + goto error; + } + + /* Call the function containing the callsite in the new library. */ + fct_ptr[1](); + + ret = dlclose(handles[1]); + if (ret) { + goto error; + } + +error: + return ret; +} + +int main(int argc, const char **argv) +{ + int c, ret = 0, test = -1, nb_libraries = 0; + char **libraries = NULL; + poptContext optCon; + struct poptOption optionsTable[] = { + { "test", 't', POPT_ARG_INT, &test, 0, "Test to run", NULL }, + { "list", 'l', 0, 0, 'l', "List of tests (-t X)", NULL }, + POPT_AUTOHELP + { NULL, 0, 0, NULL, 0 } + }; + + optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); + if (argc < 2) { + poptPrintUsage(optCon, stderr, 0); + ret = -1; + goto error; + } + + while ((c = poptGetNextOpt(optCon)) >= 0) { + switch(c) { + case 'l': + print_list(); + goto error; + } + } + + /* + * Populate the libraries array with the arguments passed to the process. + */ + while (poptPeekArg(optCon) != NULL) { + nb_libraries++; + libraries = realloc(libraries, nb_libraries * sizeof(char *)); + if (!libraries) { + ret = -1; + goto error; + } + libraries[nb_libraries - 1] = (char *) poptGetArg(optCon); + } + + switch(test) { + case 0: +#if HAS_CALLSITES + ret = dl_open_all(nb_libraries, libraries); +#else + fprintf(stderr, "Test not implemented for configuration " + "(HAS_CALLSITES=%d)\n", HAS_CALLSITES == 1); +#endif + break; + case 1: +#if HAS_CALLSITES + ret = upgrade_lib(nb_libraries, libraries); +#else + fprintf(stderr, "Test not implemented for configuration " + "(HAS_CALLSITES=%d)\n", HAS_CALLSITES == 1); +#endif + break; + case 2: +#if !HAS_CALLSITES + ret = upgrade_callsite(nb_libraries, libraries); +#else + fprintf(stderr, "Test not implemented for configuration " + "(HAS_CALLSITES=%d)\n", HAS_CALLSITES == 1); +#endif + break; + default: + fprintf(stderr, "Test %d not implemented\n", test); + ret = -1; + break; + } +error: + free(libraries); + poptFreeContext(optCon); + return ret; +}