/* This testcase is part of GDB, the GNU debugger. Copyright 2024 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include typedef void (*setter_ftype) (int which, int val); __thread int tls_main_tbss_1; __thread int tls_main_tbss_2; __thread int tls_main_tdata_1 = 96; __thread int tls_main_tdata_2 = 97; extern void set_tls_lib10_var (int which, int val); extern void set_tls_lib11_var (int which, int val); volatile int data; static void set_tls_main_var (int which, int val) { switch (which) { case 1: tls_main_tbss_1 = val; break; case 2: tls_main_tbss_2 = val; break; case 3: tls_main_tdata_1 = val; break; case 4: tls_main_tdata_2 = val; break; } } void use_it (int a) { data = a; } static void * load_dso (char *dso_name, int n, setter_ftype *setterp) { char buf[80]; void *sym; void *handle = dlopen (dso_name, RTLD_NOW | RTLD_GLOBAL); if (handle == NULL) { fprintf (stderr, "dlopen of DSO '%s' failed: %s\n", dso_name, dlerror ()); exit (1); } sprintf (buf, "set_tls_lib%d_var", n); sym = dlsym (handle, buf); assert (sym != NULL); *setterp = sym; /* Some libc implementations (for some architectures) refuse to initialize TLS data structures (specifically, the DTV) without first calling dlsym on one of the TLS symbols. */ sprintf (buf, "tls_lib%d_tdata_1", n); assert (dlsym (handle, buf) != NULL); return handle; } int main (int argc, char **argv) { int i, status; setter_ftype s0, s1, s2, s3, s4, s10, s11; void *h1 = load_dso (OBJ1, 1, &s1); void *h2 = load_dso (OBJ2, 2, &s2); void *h3 = load_dso (OBJ3, 3, &s3); void *h4 = load_dso (OBJ4, 4, &s4); s0 = set_tls_main_var; s10 = set_tls_lib10_var; s11 = set_tls_lib11_var; use_it (0); /* main-breakpoint-1 */ /* Set TLS variables in main program and all libraries. */ for (i = 1; i <= 4; i++) s0 (i, 10 + i); for (i = 1; i <= 4; i++) s1 (i, 110 + i); for (i = 1; i <= 4; i++) s2 (i, 210 + i); for (i = 1; i <= 4; i++) s3 (i, 310 + i); for (i = 1; i <= 4; i++) s4 (i, 410 + i); for (i = 1; i <= 4; i++) s10 (i, 1010 + i); for (i = 1; i <= 4; i++) s11 (i, 1110 + i); use_it (0); /* main-breakpoint-2 */ /* Unload lib2 and lib3. */ status = dlclose (h2); assert (status == 0); status = dlclose (h3); assert (status == 0); /* Set TLS variables in main program and in libraries which are still loaded. */ for (i = 1; i <= 4; i++) s0 (i, 20 + i); for (i = 1; i <= 4; i++) s1 (i, 120 + i); for (i = 1; i <= 4; i++) s4 (i, 420 + i); for (i = 1; i <= 4; i++) s10 (i, 1020 + i); for (i = 1; i <= 4; i++) s11 (i, 1120 + i); use_it (0); /* main-breakpoint-3 */ /* Load lib3. */ h3 = load_dso (OBJ3, 3, &s3); /* Set TLS vars again; currently, only lib2 is not loaded. */ for (i = 1; i <= 4; i++) s0 (i, 30 + i); for (i = 1; i <= 4; i++) s1 (i, 130 + i); for (i = 1; i <= 4; i++) s3 (i, 330 + i); for (i = 1; i <= 4; i++) s4 (i, 430 + i); for (i = 1; i <= 4; i++) s10 (i, 1030 + i); for (i = 1; i <= 4; i++) s11 (i, 1130 + i); use_it (0); /* main-breakpoint-4 */ /* Unload lib1 and lib4; load lib2. */ status = dlclose (h1); assert (status == 0); status = dlclose (h4); assert (status == 0); h2 = load_dso (OBJ2, 2, &s2); /* Set TLS vars; currently, lib2 and lib3 are loaded, lib1 and lib4 are not. */ for (i = 1; i <= 4; i++) s0 (i, 40 + i); for (i = 1; i <= 4; i++) s2 (i, 240 + i); for (i = 1; i <= 4; i++) s3 (i, 340 + i); for (i = 1; i <= 4; i++) s10 (i, 1040 + i); for (i = 1; i <= 4; i++) s11 (i, 1140 + i); use_it (0); /* main-breakpoint-5 */ /* Load lib4 and lib1. Unload lib2. */ h4 = load_dso (OBJ4, 4, &s4); h1 = load_dso (OBJ1, 1, &s1); status = dlclose (h2); assert (status == 0); /* Set TLS vars; currently, lib1, lib3, and lib4 are loaded; lib2 is not loaded. */ for (i = 1; i <= 4; i++) s0 (i, 50 + i); for (i = 1; i <= 4; i++) s1 (i, 150 + i); for (i = 1; i <= 4; i++) s3 (i, 350 + i); for (i = 1; i <= 4; i++) s4 (i, 450 + i); for (i = 1; i <= 4; i++) s10 (i, 1050 + i); for (i = 1; i <= 4; i++) s11 (i, 1150 + i); use_it (0); /* main-breakpoint-6 */ /* Load lib2, unload lib1, lib3, and lib4; then load lib3 again. */ h2 = load_dso (OBJ2, 2, &s2); status = dlclose (h1); assert (status == 0); status = dlclose (h3); assert (status == 0); status = dlclose (h4); assert (status == 0); h3 = load_dso (OBJ3, 3, &s3); /* Set TLS vars; currently, lib2 and lib3 are loaded; lib1 and lib4 are not loaded. */ for (i = 1; i <= 4; i++) s0 (i, 60 + i); for (i = 1; i <= 4; i++) s2 (i, 260 + i); for (i = 1; i <= 4; i++) s3 (i, 360 + i); for (i = 1; i <= 4; i++) s10 (i, 1060 + i); for (i = 1; i <= 4; i++) s11 (i, 1160 + i); use_it (0); /* main-breakpoint-7 */ /* Unload lib3 and lib2, then (re)load lib4, lib3, lib2, and lib1, in that order. */ status = dlclose (h3); assert (status == 0); status = dlclose (h2); assert (status == 0); h4 = load_dso (OBJ4, 4, &s4); h3 = load_dso (OBJ3, 3, &s3); h2 = load_dso (OBJ2, 2, &s2); h1 = load_dso (OBJ1, 1, &s1); /* Set TLS vars; currently, lib1, lib2, lib3, and lib4 are all loaded. */ for (i = 1; i <= 4; i++) s0 (i, 70 + i); for (i = 1; i <= 4; i++) s1 (i, 170 + i); for (i = 1; i <= 4; i++) s2 (i, 270 + i); for (i = 1; i <= 4; i++) s3 (i, 370 + i); for (i = 1; i <= 4; i++) s4 (i, 470 + i); for (i = 1; i <= 4; i++) s10 (i, 1070 + i); for (i = 1; i <= 4; i++) s11 (i, 1170 + i); use_it (0); /* main-breakpoint-8 */ /* Unload lib3, lib1, and lib4. */ status = dlclose (h3); assert (status == 0); status = dlclose (h1); assert (status == 0); status = dlclose (h4); assert (status == 0); /* Set TLS vars; currently, lib2 is loaded; lib1, lib3, and lib4 are not. */ for (i = 1; i <= 4; i++) s0 (i, 80 + i); for (i = 1; i <= 4; i++) s2 (i, 280 + i); for (i = 1; i <= 4; i++) s10 (i, 1080 + i); for (i = 1; i <= 4; i++) s11 (i, 1180 + i); use_it (0); /* main-breakpoint-9 */ /* Load lib3, unload lib2, load lib4. */ h3 = load_dso (OBJ3, 3, &s3); status = dlclose (h2); assert (status == 0); h4 = load_dso (OBJ4, 4, &s4); /* Set TLS vars; currently, lib3 and lib4 are loaded; lib1 and lib2 are not. */ for (i = 1; i <= 4; i++) s0 (i, 90 + i); for (i = 1; i <= 4; i++) s3 (i, 390 + i); for (i = 1; i <= 4; i++) s4 (i, 490 + i); for (i = 1; i <= 4; i++) s10 (i, 1090 + i); for (i = 1; i <= 4; i++) s11 (i, 1190 + i); use_it (0); /* main-breakpoint-10 */ /* Attempt to keep variables in the main program from being optimized away. */ use_it (tls_main_tbss_1); use_it (tls_main_tbss_2); use_it (tls_main_tdata_1); use_it (tls_main_tdata_2); use_it (100); /* main-breakpoint-last */ return 0; }