]>
Commit | Line | Data |
---|---|---|
1 | /* Copyright (C) 2000-2019 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 | <http://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 libaries 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 ("\ | |
57 | The handling of `.protected' seems to be implemented incorrectly: giving up"); | |
58 | abort (); | |
59 | } | |
60 | puts ("`.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 ("`protlocal' in main and mod1 have same address"); | |
68 | res = 1; | |
69 | } | |
70 | if (protlocal == getlocal2 ()) | |
71 | { | |
72 | puts ("`protlocal' in main and mod2 have same address"); | |
73 | res = 1; | |
74 | } | |
75 | if (getlocal1 () == getlocal2 ()) | |
76 | { | |
77 | puts ("`protlocal' in mod1 and mod2 have same address"); | |
78 | res = 1; | |
79 | } | |
80 | if (getlocal1 () () + getlocal2 () () != 0x44) | |
81 | { | |
82 | puts ("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 ("&protinmod in main (%p) != &protinmod in mod1 (%p)\n", | |
93 | protinmod, getinmod1 ()); | |
94 | res = 1; | |
95 | } | |
96 | if (protinmod == getinmod2 ()) | |
97 | { | |
98 | puts ("`protinmod' in main and mod2 have same address"); | |
99 | res = 1; | |
100 | } | |
101 | if (getinmod1 () == getinmod2 ()) | |
102 | { | |
103 | puts ("`protinmod' in mod1 and mod2 have same address"); | |
104 | res = 1; | |
105 | } | |
106 | if (protinmod () + getinmod1 () () + getinmod2 () () != 0x4800) | |
107 | { | |
108 | puts ("pointers to `protinmod' in mod1 or mod2 incorrect"); | |
109 | res = 1; | |
110 | } | |
111 | val = protinmod () + callinmod1 () + callinmod2 (); | |
112 | if (val != 0x15800) | |
113 | { | |
114 | printf ("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 ("&protitcpt in main (%p) != &protitcpt in mod3 (%p)\n", | |
124 | &protitcpt, getitcpt3 ()); | |
125 | res = 1; | |
126 | } | |
127 | if (protitcpt == getitcpt1 ()) | |
128 | { | |
129 | puts ("`protitcpt' in main and mod1 have same address"); | |
130 | res = 1; | |
131 | } | |
132 | if (protitcpt == getitcpt2 ()) | |
133 | { | |
134 | puts ("`protitcpt' in main and mod2 have same address"); | |
135 | res = 1; | |
136 | } | |
137 | if (getitcpt1 () == getitcpt2 ()) | |
138 | { | |
139 | puts ("`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 ("\ | |
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 ("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 ("`protvarlocal' in main and mod1 have same address"); | |
161 | res = 1; | |
162 | } | |
163 | if (&protvarlocal == getvarlocal2 ()) | |
164 | { | |
165 | puts ("`protvarlocal' in main and mod2 have same address"); | |
166 | res = 1; | |
167 | } | |
168 | if (getvarlocal1 () == getvarlocal2 ()) | |
169 | { | |
170 | puts ("`protvarlocal' in mod1 and mod2 have same address"); | |
171 | res = 1; | |
172 | } | |
173 | if (strcmp (protvarlocal, __FILE__) != 0) | |
174 | { | |
175 | puts ("`protvarlocal in main has wrong value"); | |
176 | res = 1; | |
177 | } | |
178 | if (strcmp (*getvarlocal1 (), "vismod1.c") != 0) | |
179 | { | |
180 | puts ("`getvarlocal1' returns wrong value"); | |
181 | res = 1; | |
182 | } | |
183 | if (strcmp (*getvarlocal2 (), "vismod2.c") != 0) | |
184 | { | |
185 | puts ("`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 ("&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 ("`protvarinmod' in main and mod2 have same address"); | |
200 | res = 1; | |
201 | } | |
202 | if (strcmp (*getvarinmod1 (), "vismod1.c") != 0) | |
203 | { | |
204 | puts ("`getvarinmod1' returns wrong value"); | |
205 | res = 1; | |
206 | } | |
207 | if (strcmp (*getvarinmod2 (), "vismod2.c") != 0) | |
208 | { | |
209 | puts ("`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 ("`protvaritcpt' in main and mod1 have same address"); | |
217 | res = 1; | |
218 | } | |
219 | if (&protvaritcpt == getvaritcpt2 ()) | |
220 | { | |
221 | puts ("`protvaritcpt' in main and mod2 have same address"); | |
222 | res = 1; | |
223 | } | |
224 | if (&protvaritcpt != getvaritcpt3 ()) | |
225 | { | |
226 | printf ("&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 ("`protvaritcpt' in mod1 and mod2 have same address"); | |
234 | res = 1; | |
235 | } | |
236 | if (strcmp (protvaritcpt, "vismod3.c") != 0) | |
237 | { | |
238 | puts ("`protvaritcpt in main has wrong value"); | |
239 | res = 1; | |
240 | } | |
241 | if (strcmp (*getvaritcpt1 (), "vismod1.c") != 0) | |
242 | { | |
243 | puts ("`getvaritcpt1' returns wrong value"); | |
244 | res = 1; | |
245 | } | |
246 | if (strcmp (*getvaritcpt2 (), "vismod2.c") != 0) | |
247 | { | |
248 | puts ("`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 | } |