1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <assert.h>
21: #include <unistd.h>
22: #include <ldsodefs.h>
23: #include <sys/mman.h>
24: #include <dl-cache.h>
25: #include <dl-procinfo.h>
26:
27: #include <stdio-common/_itoa.h>
28:
29: #ifndef _DL_PLATFORMS_COUNT
30: # define _DL_PLATFORMS_COUNT 0
31: #endif
32:
33:
34: static struct cache_file *cache;
35: static struct cache_file_new *cache_new;
36: static size_t cachesize;
37:
38:
39: #define _dl_cache_verify_ptr(ptr) (ptr < cache_data_size)
40:
41: #define SEARCH_CACHE(cache) \
42:
43:
44:
45: \
46: do \
47: { \
48: left = 0; \
49: right = cache->nlibs - 1; \
50: \
51: while (left <= right) \
52: { \
53: __typeof__ (cache->libs[0].key) key; \
54: \
55: middle = (left + right) / 2; \
56: \
57: key = cache->libs[middle].key; \
58: \
59:
60: \
61: if (! _dl_cache_verify_ptr (key)) \
62: { \
63: cmpres = 1; \
64: break; \
65: } \
66: \
67: \
68: cmpres = _dl_cache_libcmp (name, cache_data + key); \
69: if (__builtin_expect (cmpres == 0, 0)) \
70: { \
71:
72: \
73: left = middle; \
74: \
75:
76: \
77: while (middle > 0) \
78: { \
79: __typeof__ (cache->libs[0].key) key; \
80: \
81: key = cache->libs[middle - 1].key; \
82:
83: \
84: if (! _dl_cache_verify_ptr (key) \
85: \
86: || _dl_cache_libcmp (name, cache_data + key) != 0) \
87: break; \
88: --middle; \
89: } \
90: \
91: do \
92: { \
93: int flags; \
94: __typeof__ (cache->libs[0]) *lib = &cache->libs[middle]; \
95: \
96: \
97: if (middle > left \
98:
99:
100: \
101: && (! _dl_cache_verify_ptr (lib->key) \
102: || (_dl_cache_libcmp (name, cache_data + lib->key) \
103: != 0))) \
104: break; \
105: \
106: flags = lib->flags; \
107: if (_dl_cache_check_flags (flags) \
108: && _dl_cache_verify_ptr (lib->value)) \
109: { \
110: if (best == NULL || flags == GLRO(dl_correct_cache_id)) \
111: { \
112: HWCAP_CHECK; \
113: best = cache_data + lib->value; \
114: \
115: if (flags == GLRO(dl_correct_cache_id)) \
116:
117:
118: \
119: break; \
120: } \
121: } \
122: } \
123: while (++middle <= right); \
124: break; \
125: } \
126: \
127: if (cmpres < 0) \
128: left = middle + 1; \
129: else \
130: right = middle - 1; \
131: } \
132: } \
133: while (0)
134:
135:
136: int
137: internal_function
138: _dl_cache_libcmp (const char *p1, const char *p2)
139: {
140: while (*p1 != '\0')
141: {
142: if (*p1 >= '0' && *p1 <= '9')
143: {
144: if (*p2 >= '0' && *p2 <= '9')
145: {
146:
147: int val1;
148: int val2;
149:
150: val1 = *p1++ - '0';
151: val2 = *p2++ - '0';
152: while (*p1 >= '0' && *p1 <= '9')
153: val1 = val1 * 10 + *p1++ - '0';
154: while (*p2 >= '0' && *p2 <= '9')
155: val2 = val2 * 10 + *p2++ - '0';
156: if (val1 != val2)
157: return val1 - val2;
158: }
159: else
160: return 1;
161: }
162: else if (*p2 >= '0' && *p2 <= '9')
163: return -1;
164: else if (*p1 != *p2)
165: return *p1 - *p2;
166: else
167: {
168: ++p1;
169: ++p2;
170: }
171: }
172: return *p1 - *p2;
173: }
174:
175:
176:
177:
178:
179: const char *
180: internal_function
181: _dl_load_cache_lookup (const char *name)
182: {
183: int left, right, middle;
184: int cmpres;
185: const char *cache_data;
186: uint32_t cache_data_size;
187: const char *best;
188:
189:
190: if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
191: _dl_debug_printf (" search cache=%s\n", LD_SO_CACHE);
192:
193: if (cache == NULL)
194: {
195:
196: void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &cachesize,
197: PROT_READ);
198:
199:
200:
201:
202:
203:
204: if (file != MAP_FAILED && cachesize > sizeof *cache
205: && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0)
206: {
207: size_t offset;
208:
209: cache = file;
210:
211:
212: offset = ALIGN_CACHE (sizeof (struct cache_file)
213: + cache->nlibs * sizeof (struct file_entry));
214:
215: cache_new = (struct cache_file_new *) ((void *) cache + offset);
216: if (cachesize < (offset + sizeof (struct cache_file_new))
217: || memcmp (cache_new->magic, CACHEMAGIC_VERSION_NEW,
218: sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
219: cache_new = (void *) -1;
220: }
221: else if (file != MAP_FAILED && cachesize > sizeof *cache_new
222: && memcmp (file, CACHEMAGIC_VERSION_NEW,
223: sizeof CACHEMAGIC_VERSION_NEW - 1) == 0)
224: {
225: cache_new = file;
226: cache = file;
227: }
228: else
229: {
230: if (file != MAP_FAILED)
231: __munmap (file, cachesize);
232: cache = (void *) -1;
233: }
234:
235: assert (cache != NULL);
236: }
237:
238: if (cache == (void *) -1)
239:
240: return NULL;
241:
242: best = NULL;
243:
244: if (cache_new != (void *) -1)
245: {
246: uint64_t platform;
247:
248:
249: cache_data = (const char *) cache_new;
250:
251:
252: cache_data_size = (const char *) cache + cachesize - cache_data;
253:
254: platform = _dl_string_platform (GLRO(dl_platform));
255: if (platform != (uint64_t) -1)
256: platform = 1ULL << platform;
257:
258:
259: #define _DL_HWCAP_TLS_MASK (1LL << 63)
260: #define HWCAP_CHECK \
261: if (GLRO(dl_osversion) && lib->osversion > GLRO(dl_osversion)) \
262: continue; \
263: if (_DL_PLATFORMS_COUNT \
264: && (lib->hwcap & _DL_HWCAP_PLATFORM) != 0 \
265: && (lib->hwcap & _DL_HWCAP_PLATFORM) != platform) \
266: continue; \
267: if (lib->hwcap \
268: & ~(GLRO(dl_hwcap) | _DL_HWCAP_PLATFORM | _DL_HWCAP_TLS_MASK)) \
269: continue
270: SEARCH_CACHE (cache_new);
271: }
272: else
273: {
274:
275: cache_data = (const char *) &cache->libs[cache->nlibs];
276:
277:
278: cache_data_size = (const char *) cache + cachesize - cache_data;
279:
280: #undef HWCAP_CHECK
281: #define HWCAP_CHECK do {} while (0)
282: SEARCH_CACHE (cache);
283: }
284:
285:
286: if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0)
287: && best != NULL)
288: _dl_debug_printf (" trying file=%s\n", best);
289:
290: return best;
291: }
292:
293: #ifndef MAP_COPY
294:
295:
296:
297:
298: void
299: _dl_unload_cache (void)
300: {
301: if (cache != NULL && cache != (struct cache_file *) -1)
302: {
303: __munmap (cache, cachesize);
304: cache = NULL;
305: }
306: }
307: #endif