1 | /* Copyright (C) 2000-2024 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) any later version. |
8 | |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with the GNU C Library; if not, see |
16 | <https://www.gnu.org/licenses/>. */ |
17 | |
18 | /* This file must be compiled as PIE to avoid copy relocation when |
19 | accessing protected symbols defined in shared libraries since copy |
20 | relocation doesn't work with protected symbols and linker in |
21 | binutils 2.26 enforces this rule. */ |
22 | |
23 | #include <stdio.h> |
24 | #include <stdlib.h> |
25 | #include <string.h> |
26 | |
27 | #include "vismod.h" |
28 | |
29 | /* Prototype for our test function. */ |
30 | extern int do_test (void); |
31 | |
32 | |
33 | /* This defines the `main' function and some more. */ |
34 | #include <support/test-driver.c> |
35 | |
36 | |
37 | /* Prototypes for local functions. */ |
38 | extern int protlocal (void); |
39 | |
40 | const char *protvarlocal = __FILE__; |
41 | extern const char *protvarinmod; |
42 | extern const char *protvaritcpt; |
43 | |
44 | int |
45 | do_test (void) |
46 | { |
47 | int res = 0; |
48 | int val; |
49 | |
50 | /* First test: check whether .protected is handled correctly by the |
51 | assembler/linker. The uses of `protlocal' in the DSOs and in the |
52 | main program should all be resolved with the local definitions. */ |
53 | val = protlocal () + calllocal1 () + calllocal2 (); |
54 | if (val != 0x155) |
55 | { |
56 | puts (s: "\ |
57 | The handling of `.protected' seems to be implemented incorrectly: giving up" ); |
58 | abort (); |
59 | } |
60 | puts (s: "`.protected' seems to be handled correctly, good!" ); |
61 | |
62 | /* Function pointers: for functions which are marked local and for |
63 | which definitions are available all function pointers must be |
64 | distinct. */ |
65 | if (protlocal == getlocal1 ()) |
66 | { |
67 | puts (s: "`protlocal' in main and mod1 have same address" ); |
68 | res = 1; |
69 | } |
70 | if (protlocal == getlocal2 ()) |
71 | { |
72 | puts (s: "`protlocal' in main and mod2 have same address" ); |
73 | res = 1; |
74 | } |
75 | if (getlocal1 () == getlocal2 ()) |
76 | { |
77 | puts (s: "`protlocal' in mod1 and mod2 have same address" ); |
78 | res = 1; |
79 | } |
80 | if (getlocal1 () () + getlocal2 () () != 0x44) |
81 | { |
82 | puts (s: "pointers to `protlocal' in mod1 or mod2 incorrect" ); |
83 | res = 1; |
84 | } |
85 | |
86 | /* Next test. This is similar to the last one but the function we |
87 | are calling is not defined in the main object. This means that |
88 | the invocation in the main object uses the definition in the |
89 | first DSO. */ |
90 | if (protinmod != getinmod1 ()) |
91 | { |
92 | printf (format: "&protinmod in main (%p) != &protinmod in mod1 (%p)\n" , |
93 | protinmod, getinmod1 ()); |
94 | res = 1; |
95 | } |
96 | if (protinmod == getinmod2 ()) |
97 | { |
98 | puts (s: "`protinmod' in main and mod2 have same address" ); |
99 | res = 1; |
100 | } |
101 | if (getinmod1 () == getinmod2 ()) |
102 | { |
103 | puts (s: "`protinmod' in mod1 and mod2 have same address" ); |
104 | res = 1; |
105 | } |
106 | if (protinmod () + getinmod1 () () + getinmod2 () () != 0x4800) |
107 | { |
108 | puts (s: "pointers to `protinmod' in mod1 or mod2 incorrect" ); |
109 | res = 1; |
110 | } |
111 | val = protinmod () + callinmod1 () + callinmod2 (); |
112 | if (val != 0x15800) |
113 | { |
114 | printf (format: "calling of `protinmod' leads to wrong result (%#x)\n" , val); |
115 | res = 1; |
116 | } |
117 | |
118 | /* A very similar text. Same setup for the main object and the modules |
119 | but this time we have another definition in a preloaded module. This |
120 | one intercepts the references from the main object. */ |
121 | if (protitcpt != getitcpt3 ()) |
122 | { |
123 | printf (format: "&protitcpt in main (%p) != &protitcpt in mod3 (%p)\n" , |
124 | &protitcpt, getitcpt3 ()); |
125 | res = 1; |
126 | } |
127 | if (protitcpt == getitcpt1 ()) |
128 | { |
129 | puts (s: "`protitcpt' in main and mod1 have same address" ); |
130 | res = 1; |
131 | } |
132 | if (protitcpt == getitcpt2 ()) |
133 | { |
134 | puts (s: "`protitcpt' in main and mod2 have same address" ); |
135 | res = 1; |
136 | } |
137 | if (getitcpt1 () == getitcpt2 ()) |
138 | { |
139 | puts (s: "`protitcpt' in mod1 and mod2 have same address" ); |
140 | res = 1; |
141 | } |
142 | val = protitcpt () + getitcpt1 () () + getitcpt2 () () + getitcpt3 () (); |
143 | if (val != 0x8440000) |
144 | { |
145 | printf (format: "\ |
146 | pointers to `protitcpt' in mod1 or mod2 or mod3 incorrect (%#x)\n" , val); |
147 | res = 1; |
148 | } |
149 | val = protitcpt () + callitcpt1 () + callitcpt2 () + callitcpt3 (); |
150 | if (val != 0x19540000) |
151 | { |
152 | printf (format: "calling of `protitcpt' leads to wrong result (%#x)\n" , val); |
153 | res = 1; |
154 | } |
155 | |
156 | /* Now look at variables. First a variable which is available |
157 | everywhere. We must have three different addresses. */ |
158 | if (&protvarlocal == getvarlocal1 ()) |
159 | { |
160 | puts (s: "`protvarlocal' in main and mod1 have same address" ); |
161 | res = 1; |
162 | } |
163 | if (&protvarlocal == getvarlocal2 ()) |
164 | { |
165 | puts (s: "`protvarlocal' in main and mod2 have same address" ); |
166 | res = 1; |
167 | } |
168 | if (getvarlocal1 () == getvarlocal2 ()) |
169 | { |
170 | puts (s: "`protvarlocal' in mod1 and mod2 have same address" ); |
171 | res = 1; |
172 | } |
173 | if (strcmp (s1: protvarlocal, __FILE__) != 0) |
174 | { |
175 | puts (s: "`protvarlocal in main has wrong value" ); |
176 | res = 1; |
177 | } |
178 | if (strcmp (s1: *getvarlocal1 (), s2: "vismod1.c" ) != 0) |
179 | { |
180 | puts (s: "`getvarlocal1' returns wrong value" ); |
181 | res = 1; |
182 | } |
183 | if (strcmp (s1: *getvarlocal2 (), s2: "vismod2.c" ) != 0) |
184 | { |
185 | puts (s: "`getvarlocal2' returns wrong value" ); |
186 | res = 1; |
187 | } |
188 | |
189 | /* Now the case where there is no local definition. */ |
190 | if (&protvarinmod != getvarinmod1 ()) |
191 | { |
192 | printf (format: "&protvarinmod in main (%p) != &protitcpt in mod1 (%p)\n" , |
193 | &protvarinmod, getvarinmod1 ()); |
194 | // XXX Possibly enable once fixed. |
195 | // res = 1; |
196 | } |
197 | if (&protvarinmod == getvarinmod2 ()) |
198 | { |
199 | puts (s: "`protvarinmod' in main and mod2 have same address" ); |
200 | res = 1; |
201 | } |
202 | if (strcmp (s1: *getvarinmod1 (), s2: "vismod1.c" ) != 0) |
203 | { |
204 | puts (s: "`getvarinmod1' returns wrong value" ); |
205 | res = 1; |
206 | } |
207 | if (strcmp (s1: *getvarinmod2 (), s2: "vismod2.c" ) != 0) |
208 | { |
209 | puts (s: "`getvarinmod2' returns wrong value" ); |
210 | res = 1; |
211 | } |
212 | |
213 | /* And a test where a variable definition is intercepted. */ |
214 | if (&protvaritcpt == getvaritcpt1 ()) |
215 | { |
216 | puts (s: "`protvaritcpt' in main and mod1 have same address" ); |
217 | res = 1; |
218 | } |
219 | if (&protvaritcpt == getvaritcpt2 ()) |
220 | { |
221 | puts (s: "`protvaritcpt' in main and mod2 have same address" ); |
222 | res = 1; |
223 | } |
224 | if (&protvaritcpt != getvaritcpt3 ()) |
225 | { |
226 | printf (format: "&protvaritcpt in main (%p) != &protvaritcpt in mod3 (%p)\n" , |
227 | &protvaritcpt, getvaritcpt3 ()); |
228 | // XXX Possibly enable once fixed. |
229 | // res = 1; |
230 | } |
231 | if (getvaritcpt1 () == getvaritcpt2 ()) |
232 | { |
233 | puts (s: "`protvaritcpt' in mod1 and mod2 have same address" ); |
234 | res = 1; |
235 | } |
236 | if (strcmp (s1: protvaritcpt, s2: "vismod3.c" ) != 0) |
237 | { |
238 | puts (s: "`protvaritcpt in main has wrong value" ); |
239 | res = 1; |
240 | } |
241 | if (strcmp (s1: *getvaritcpt1 (), s2: "vismod1.c" ) != 0) |
242 | { |
243 | puts (s: "`getvaritcpt1' returns wrong value" ); |
244 | res = 1; |
245 | } |
246 | if (strcmp (s1: *getvaritcpt2 (), s2: "vismod2.c" ) != 0) |
247 | { |
248 | puts (s: "`getvaritcpt2' returns wrong value" ); |
249 | res = 1; |
250 | } |
251 | |
252 | return res; |
253 | } |
254 | |
255 | |
256 | int |
257 | protlocal (void) |
258 | { |
259 | return 0x1; |
260 | } |
261 | |