1 /* Test interactions of dlopen, NODELETE, and relocations.
2 Copyright (C) 2019-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 /* This test exercises NODELETE propagation due to data relocations
20 and unique symbols, and the interaction with already-loaded
21 objects. Some test objects are written in C++, to produce unique
24 First test: Global scope variant, data relocation as the NODELETE
25 trigger. mod1 is loaded first with a separate dlopen call.
27 mod2 ---(may_finalize_mod1 relocation dependency)---> mod1
28 (NODELETE) (marked as NODELETE)
30 Second test: Local scope variant, data relocation. mod3 is loaded
33 mod5 ---(DT_NEEDED)---> mod4 ---(DT_NEEDED)---> mod3
34 (NODELETE) (not NODELETE) ^
36 `--(may_finalize_mod3 relocation dependency)--/ NODELETE)
38 Third test: Shared local scope with unique symbol. mod6 is loaded
39 first, then mod7. No explicit dependencies between the two
40 objects, so first object has to be opened with RTLD_GLOBAL.
42 mod7 ---(unique symbol)---> mod6
45 Forth test: Non-shared scopes with unique symbol. mod8 and mod10
46 are loaded from the main program. mod8 loads mod9 from an ELF
47 constructor, mod10 loads mod11. There are no DT_NEEDED
48 dependencies. mod9 is promoted to the global scope form the main
49 program. The unique symbol dependency is:
51 mod9 ---(unique symbol)---> mod11
54 Fifth test: Shared local scope with unique symbol, like test 3, but
55 this time, there is also a DT_NEEDED dependency (so no RTLD_GLOBAL
59 mod13 ---(unique symbol)---> mod12
62 Sixth test: NODELETE status is retained after relocation failure
63 with unique symbol dependency. The object graph ensures that the
64 unique symbol binding is processed before the dlopen failure.
67 mod17 --(DT_NEEDED)--> mod15 --(unique symbol)--> mod14
71 `---(DT_NEEDED)--> mod16
74 mod14 is loaded first, and the loading mod17 is attempted.
75 mod14 must remain NODELETE after opening mod17 failed. */
80 #include <support/check.h>
81 #include <support/xdlfcn.h>
86 /* First case: global scope, regular data symbol. Open the object
87 which is not NODELETE initially. */
88 void *mod1
= xdlopen ("tst-dlopen-nodelete-reloc-mod1.so",
89 RTLD_NOW
| RTLD_GLOBAL
);
90 /* This is used to indicate that the ELF destructor may be
92 bool *may_finalize_mod1
= xdlsym (mod1
, "may_finalize_mod1");
93 /* Open the NODELETE object. */
94 void *mod2
= xdlopen ("tst-dlopen-nodelete-reloc-mod2.so", RTLD_NOW
);
95 /* This has no effect because the DSO is directly marked as
98 /* This has no effect because the DSO has been indirectly marked as
99 NODELETE due to a relocation dependency. */
102 /* Second case: local scope, regular data symbol. Open the object
103 which is not NODELETE initially. */
104 void *mod3
= xdlopen ("tst-dlopen-nodelete-reloc-mod3.so", RTLD_NOW
);
105 bool *may_finalize_mod3
= xdlsym (mod3
, "may_finalize_mod3");
106 /* Open the NODELETE object. */
107 void *mod5
= xdlopen ("tst-dlopen-nodelete-reloc-mod5.so", RTLD_NOW
);
108 /* Again those have no effect because of NODELETE. */
112 /* Third case: Unique symbol. */
113 void *mod6
= xdlopen ("tst-dlopen-nodelete-reloc-mod6.so",
114 RTLD_NOW
| RTLD_GLOBAL
);
115 bool *may_finalize_mod6
= xdlsym (mod6
, "may_finalize_mod6");
116 void *mod7
= xdlopen ("tst-dlopen-nodelete-reloc-mod7.so", RTLD_NOW
);
117 bool *may_finalize_mod7
= xdlsym (mod7
, "may_finalize_mod7");
118 /* This should not have any effect because of the unique symbol and
119 the resulting NODELETE status. */
121 /* mod7 is not NODELETE and can be closed. */
122 *may_finalize_mod7
= true;
125 /* Fourth case: Unique symbol, indirect loading. */
126 void *mod8
= xdlopen ("tst-dlopen-nodelete-reloc-mod8.so", RTLD_NOW
);
127 /* Also promote to global scope. */
128 void *mod9
= xdlopen ("tst-dlopen-nodelete-reloc-mod9.so",
129 RTLD_NOW
| RTLD_NOLOAD
| RTLD_GLOBAL
);
130 bool *may_finalize_mod9
= xdlsym (mod9
, "may_finalize_mod9");
131 xdlclose (mod9
); /* Drop mod9 reference. */
132 void *mod10
= xdlopen ("tst-dlopen-nodelete-reloc-mod10.so", RTLD_NOW
);
133 void *mod11
= xdlopen ("tst-dlopen-nodelete-reloc-mod11.so",
134 RTLD_NOW
| RTLD_NOLOAD
);
135 bool *may_finalize_mod11
= xdlsym (mod11
, "may_finalize_mod11");
136 xdlclose (mod11
); /* Drop mod11 reference. */
137 /* mod11 is not NODELETE and can be closed. */
138 *may_finalize_mod11
= true;
139 /* Trigger closing of mod11, too. */
141 /* Does not trigger closing of mod9. */
144 /* Fifth case: Unique symbol, with DT_NEEDED dependency. */
145 void *mod12
= xdlopen ("tst-dlopen-nodelete-reloc-mod12.so", RTLD_NOW
);
146 bool *may_finalize_mod12
= xdlsym (mod12
, "may_finalize_mod12");
147 void *mod13
= xdlopen ("tst-dlopen-nodelete-reloc-mod13.so", RTLD_NOW
);
148 bool *may_finalize_mod13
= xdlsym (mod13
, "may_finalize_mod13");
149 /* This should not have any effect because of the unique symbol. */
151 /* mod13 is not NODELETE and can be closed. */
152 *may_finalize_mod13
= true;
155 /* Sixth case: Unique symbol binding must not cause loss of NODELETE
157 void *mod14
= xdlopen ("tst-dlopen-nodelete-reloc-mod14.so",
158 RTLD_NOW
| RTLD_NODELETE
);
159 bool *may_finalize_mod14
= xdlsym (mod14
, "may_finalize_mod14");
160 TEST_VERIFY (dlopen ("tst-dlopen-nodelete-reloc-mod17.so", RTLD_NOW
)
162 const char *message
= dlerror ();
163 printf ("info: test 6 message: %s\n", message
);
164 /* This must not close the object, it must still be NODELETE. */
166 xdlopen ("tst-dlopen-nodelete-reloc-mod14.so", RTLD_NOW
| RTLD_NOLOAD
);
168 /* Prepare for process exit. Destructors for NODELETE objects will
170 *may_finalize_mod1
= true;
171 *may_finalize_mod3
= true;
172 *may_finalize_mod6
= true;
173 *may_finalize_mod9
= true;
174 *may_finalize_mod12
= true;
175 *may_finalize_mod14
= true;
179 #include <support/test-driver.c>