rtld: properly handle root directory in load path (bug 30435)
[platform/upstream/glibc.git] / elf / vismain.c
1 /* Copyright (C) 2000-2023 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 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 }