Merge remote branch 'origin/roland/hwcap_mask'
[platform/upstream/glibc.git] / elf / dl-cache.c
1 /* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
2    Copyright (C) 1996-2002,2003,2004,2006,2010
3         Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #include <assert.h>
22 #include <unistd.h>
23 #include <ldsodefs.h>
24 #include <sys/mman.h>
25 #include <dl-cache.h>
26 #include <dl-procinfo.h>
27
28 #include <stdio-common/_itoa.h>
29
30 #ifndef _DL_PLATFORMS_COUNT
31 # define _DL_PLATFORMS_COUNT 0
32 #endif
33
34 /* This is the starting address and the size of the mmap()ed file.  */
35 static struct cache_file *cache;
36 static struct cache_file_new *cache_new;
37 static size_t cachesize;
38
39 /* 1 if cache_data + PTR points into the cache.  */
40 #define _dl_cache_verify_ptr(ptr) (ptr < cache_data_size)
41
42 #define SEARCH_CACHE(cache) \
43 /* We use binary search since the table is sorted in the cache file.          \
44    The first matching entry in the table is returned.                         \
45    It is important to use the same algorithm as used while generating         \
46    the cache file.  */                                                        \
47 do                                                                            \
48   {                                                                           \
49     left = 0;                                                                 \
50     right = cache->nlibs - 1;                                                 \
51                                                                               \
52     while (left <= right)                                                     \
53       {                                                                       \
54         __typeof__ (cache->libs[0].key) key;                                  \
55                                                                               \
56         middle = (left + right) / 2;                                          \
57                                                                               \
58         key = cache->libs[middle].key;                                        \
59                                                                               \
60         /* Make sure string table indices are not bogus before using          \
61            them.  */                                                          \
62         if (! _dl_cache_verify_ptr (key))                                     \
63           {                                                                   \
64             cmpres = 1;                                                       \
65             break;                                                            \
66           }                                                                   \
67                                                                               \
68         /* Actually compare the entry with the key.  */                       \
69         cmpres = _dl_cache_libcmp (name, cache_data + key);                   \
70         if (__builtin_expect (cmpres == 0, 0))                                \
71           {                                                                   \
72             /* Found it.  LEFT now marks the last entry for which we          \
73                know the name is correct.  */                                  \
74             left = middle;                                                    \
75                                                                               \
76             /* There might be entries with this name before the one we        \
77                found.  So we have to find the beginning.  */                  \
78             while (middle > 0)                                                \
79               {                                                               \
80                 __typeof__ (cache->libs[0].key) key;                          \
81                                                                               \
82                 key = cache->libs[middle - 1].key;                            \
83                 /* Make sure string table indices are not bogus before        \
84                    using them.  */                                            \
85                 if (! _dl_cache_verify_ptr (key)                              \
86                     /* Actually compare the entry.  */                        \
87                     || _dl_cache_libcmp (name, cache_data + key) != 0)        \
88                   break;                                                      \
89                 --middle;                                                     \
90               }                                                               \
91                                                                               \
92             do                                                                \
93               {                                                               \
94                 int flags;                                                    \
95                 __typeof__ (cache->libs[0]) *lib = &cache->libs[middle];      \
96                                                                               \
97                 /* Only perform the name test if necessary.  */               \
98                 if (middle > left                                             \
99                     /* We haven't seen this string so far.  Test whether the  \
100                        index is ok and whether the name matches.  Otherwise   \
101                        we are done.  */                                       \
102                     && (! _dl_cache_verify_ptr (lib->key)                     \
103                         || (_dl_cache_libcmp (name, cache_data + lib->key)    \
104                             != 0)))                                           \
105                   break;                                                      \
106                                                                               \
107                 flags = lib->flags;                                           \
108                 if (_dl_cache_check_flags (flags)                             \
109                     && _dl_cache_verify_ptr (lib->value))                     \
110                   {                                                           \
111                     if (best == NULL || flags == GLRO(dl_correct_cache_id))   \
112                       {                                                       \
113                         HWCAP_CHECK;                                          \
114                         best = cache_data + lib->value;                       \
115                                                                               \
116                         if (flags == GLRO(dl_correct_cache_id))               \
117                           /* We've found an exact match for the shared        \
118                              object and no general `ELF' release.  Stop       \
119                              searching.  */                                   \
120                           break;                                              \
121                       }                                                       \
122                   }                                                           \
123               }                                                               \
124             while (++middle <= right);                                        \
125             break;                                                            \
126         }                                                                     \
127                                                                               \
128         if (cmpres < 0)                                                       \
129           left = middle + 1;                                                  \
130         else                                                                  \
131           right = middle - 1;                                                 \
132       }                                                                       \
133   }                                                                           \
134 while (0)
135
136
137 int
138 internal_function
139 _dl_cache_libcmp (const char *p1, const char *p2)
140 {
141   while (*p1 != '\0')
142     {
143       if (*p1 >= '0' && *p1 <= '9')
144         {
145           if (*p2 >= '0' && *p2 <= '9')
146             {
147               /* Must compare this numerically.  */
148               int val1;
149               int val2;
150
151               val1 = *p1++ - '0';
152               val2 = *p2++ - '0';
153               while (*p1 >= '0' && *p1 <= '9')
154                 val1 = val1 * 10 + *p1++ - '0';
155               while (*p2 >= '0' && *p2 <= '9')
156                 val2 = val2 * 10 + *p2++ - '0';
157               if (val1 != val2)
158                 return val1 - val2;
159             }
160           else
161             return 1;
162         }
163       else if (*p2 >= '0' && *p2 <= '9')
164         return -1;
165       else if (*p1 != *p2)
166         return *p1 - *p2;
167       else
168         {
169           ++p1;
170           ++p2;
171         }
172     }
173   return *p1 - *p2;
174 }
175
176
177 /* Look up NAME in ld.so.cache and return the file name stored there,
178    or null if none is found.  */
179
180 const char *
181 internal_function
182 _dl_load_cache_lookup (const char *name)
183 {
184   int left, right, middle;
185   int cmpres;
186   const char *cache_data;
187   uint32_t cache_data_size;
188   const char *best;
189
190   /* Print a message if the loading of libs is traced.  */
191   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
192     _dl_debug_printf (" search cache=%s\n", LD_SO_CACHE);
193
194   if (cache == NULL)
195     {
196       /* Read the contents of the file.  */
197       void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &cachesize,
198                                                PROT_READ);
199
200       /* We can handle three different cache file formats here:
201          - the old libc5/glibc2.0/2.1 format
202          - the old format with the new format in it
203          - only the new format
204          The following checks if the cache contains any of these formats.  */
205       if (file != MAP_FAILED && cachesize > sizeof *cache
206           && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0)
207         {
208           size_t offset;
209           /* Looks ok.  */
210           cache = file;
211
212           /* Check for new version.  */
213           offset = ALIGN_CACHE (sizeof (struct cache_file)
214                                 + cache->nlibs * sizeof (struct file_entry));
215
216           cache_new = (struct cache_file_new *) ((void *) cache + offset);
217           if (cachesize < (offset + sizeof (struct cache_file_new))
218               || memcmp (cache_new->magic, CACHEMAGIC_VERSION_NEW,
219                          sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
220             cache_new = (void *) -1;
221         }
222       else if (file != MAP_FAILED && cachesize > sizeof *cache_new
223                && memcmp (file, CACHEMAGIC_VERSION_NEW,
224                           sizeof CACHEMAGIC_VERSION_NEW - 1) == 0)
225         {
226           cache_new = file;
227           cache = file;
228         }
229       else
230         {
231           if (file != MAP_FAILED)
232             __munmap (file, cachesize);
233           cache = (void *) -1;
234         }
235
236       assert (cache != NULL);
237     }
238
239   if (cache == (void *) -1)
240     /* Previously looked for the cache file and didn't find it.  */
241     return NULL;
242
243   best = NULL;
244
245   if (cache_new != (void *) -1)
246     {
247       uint64_t platform;
248
249       /* This is where the strings start.  */
250       cache_data = (const char *) cache_new;
251
252       /* Now we can compute how large the string table is.  */
253       cache_data_size = (const char *) cache + cachesize - cache_data;
254
255       platform = _dl_string_platform (GLRO(dl_platform));
256       if (platform != (uint64_t) -1)
257         platform = 1ULL << platform;
258
259 #define _DL_HWCAP_TLS_MASK (1LL << 63)
260       uint64_t hwcap_exclude = ~((GLRO(dl_hwcap) & GLRO(dl_hwcap_mask))
261                                  | _DL_HWCAP_PLATFORM | _DL_HWCAP_TLS_MASK);
262
263       /* Only accept hwcap if it's for the right platform.  */
264 #define HWCAP_CHECK \
265       if (lib->hwcap & hwcap_exclude)                                         \
266         continue;                                                             \
267       if (GLRO(dl_osversion) && lib->osversion > GLRO(dl_osversion))          \
268         continue;                                                             \
269       if (_DL_PLATFORMS_COUNT                                                 \
270           && (lib->hwcap & _DL_HWCAP_PLATFORM) != 0                           \
271           && (lib->hwcap & _DL_HWCAP_PLATFORM) != platform)                   \
272         continue
273       SEARCH_CACHE (cache_new);
274     }
275   else
276     {
277       /* This is where the strings start.  */
278       cache_data = (const char *) &cache->libs[cache->nlibs];
279
280       /* Now we can compute how large the string table is.  */
281       cache_data_size = (const char *) cache + cachesize - cache_data;
282
283 #undef HWCAP_CHECK
284 #define HWCAP_CHECK do {} while (0)
285       SEARCH_CACHE (cache);
286     }
287
288   /* Print our result if wanted.  */
289   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0)
290       && best != NULL)
291     _dl_debug_printf ("  trying file=%s\n", best);
292
293   return best;
294 }
295
296 #ifndef MAP_COPY
297 /* If the system does not support MAP_COPY we cannot leave the file open
298    all the time since this would create problems when the file is replaced.
299    Therefore we provide this function to close the file and open it again
300    once needed.  */
301 void
302 _dl_unload_cache (void)
303 {
304   if (cache != NULL && cache != (struct cache_file *) -1)
305     {
306       __munmap (cache, cachesize);
307       cache = NULL;
308     }
309 }
310 #endif