This source file includes following definitions.
- set_this_relocation_prefix
- set_relocation_prefix
- compute_curr_prefix
- DllMain
- _DLL_InitTerm
- find_shared_library_fullname
- get_shared_library_fullname
- relocate
- relocate2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #ifndef _GNU_SOURCE
23 # define _GNU_SOURCE 1
24 #endif
25
26 #define _GL_USE_STDLIB_ALLOC 1
27 #include <config.h>
28
29
30 #include "relocatable.h"
31
32 #if ENABLE_RELOCATABLE
33
34 #include <stddef.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #ifdef NO_XMALLOC
40 # define xmalloc malloc
41 #else
42 # include "xalloc.h"
43 #endif
44
45 #if defined _WIN32 && !defined __CYGWIN__
46 # define WIN32_LEAN_AND_MEAN
47 # include <windows.h>
48 #endif
49
50 #ifdef __EMX__
51 # define INCL_DOS
52 # include <os2.h>
53
54 # define strcmp stricmp
55 # define strncmp strnicmp
56 #endif
57
58 #if DEPENDS_ON_LIBCHARSET
59 # include <libcharset.h>
60 #endif
61 #if DEPENDS_ON_LIBICONV && HAVE_ICONV
62 # include <iconv.h>
63 #endif
64 #if DEPENDS_ON_LIBINTL && ENABLE_NLS
65 # include <libintl.h>
66 #endif
67
68 #if defined _WIN32 && !defined __CYGWIN__
69
70 # undef GetModuleFileName
71 # define GetModuleFileName GetModuleFileNameA
72 #endif
73
74
75 #undef bool
76 #undef false
77 #undef true
78 #define bool int
79 #define false 0
80 #define true 1
81
82
83
84
85
86 #if (defined _WIN32 && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
87
88 # define ISSLASH(C) ((C) == '/' || (C) == '\\')
89 # define HAS_DEVICE(P) \
90 ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
91 && (P)[1] == ':')
92 # define IS_FILE_NAME_WITH_DIR(P) \
93 (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
94 # define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
95 #else
96
97 # define ISSLASH(C) ((C) == '/')
98 # define IS_FILE_NAME_WITH_DIR(P) (strchr (P, '/') != NULL)
99 # define FILE_SYSTEM_PREFIX_LEN(P) 0
100 #endif
101
102
103
104
105
106
107 #ifndef ENABLE_COSTLY_RELOCATABLE
108 # if defined _WIN32 && !defined __CYGWIN__
109 # define ENABLE_COSTLY_RELOCATABLE 1
110 # else
111 # define ENABLE_COSTLY_RELOCATABLE 0
112 # endif
113 #endif
114
115
116 static char *orig_prefix;
117 static size_t orig_prefix_len;
118
119 static char *curr_prefix;
120 static size_t curr_prefix_len;
121
122
123
124
125
126
127
128
129 static void
130 set_this_relocation_prefix (const char *orig_prefix_arg,
131 const char *curr_prefix_arg)
132 {
133 if (orig_prefix_arg != NULL && curr_prefix_arg != NULL
134
135
136 && strcmp (orig_prefix_arg, curr_prefix_arg) != 0)
137 {
138
139 char *memory;
140
141 orig_prefix_len = strlen (orig_prefix_arg);
142 curr_prefix_len = strlen (curr_prefix_arg);
143 memory = (char *) xmalloc (orig_prefix_len + 1 + curr_prefix_len + 1);
144 #ifdef NO_XMALLOC
145 if (memory != NULL)
146 #endif
147 {
148 memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);
149 orig_prefix = memory;
150 memory += orig_prefix_len + 1;
151 memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);
152 curr_prefix = memory;
153 return;
154 }
155 }
156 orig_prefix = NULL;
157 curr_prefix = NULL;
158
159
160 }
161
162
163
164
165
166
167 void
168 set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg)
169 {
170 set_this_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
171
172
173 #if DEPENDS_ON_LIBCHARSET
174 libcharset_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
175 #endif
176 #if DEPENDS_ON_LIBICONV && HAVE_ICONV && _LIBICONV_VERSION >= 0x0109
177 libiconv_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
178 #endif
179 #if DEPENDS_ON_LIBINTL && ENABLE_NLS && defined libintl_set_relocation_prefix
180 libintl_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
181 #endif
182 }
183
184 #if !defined IN_LIBRARY || (defined PIC && defined INSTALLDIR && ENABLE_COSTLY_RELOCATABLE)
185
186
187
188
189
190
191 #ifdef IN_LIBRARY
192 #define compute_curr_prefix local_compute_curr_prefix
193 static
194 #endif
195 char *
196 compute_curr_prefix (const char *orig_installprefix,
197 const char *orig_installdir,
198 const char *curr_pathname)
199 {
200 char *curr_installdir;
201 const char *rel_installdir;
202
203 if (curr_pathname == NULL)
204 return NULL;
205
206
207
208
209 if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix))
210 != 0)
211
212 return NULL;
213 rel_installdir = orig_installdir + strlen (orig_installprefix);
214
215
216 {
217 const char *p_base = curr_pathname + FILE_SYSTEM_PREFIX_LEN (curr_pathname);
218 const char *p = curr_pathname + strlen (curr_pathname);
219 char *q;
220
221 while (p > p_base)
222 {
223 p--;
224 if (ISSLASH (*p))
225 break;
226 }
227
228 q = (char *) xmalloc (p - curr_pathname + 1);
229 #ifdef NO_XMALLOC
230 if (q == NULL)
231 return NULL;
232 #endif
233 memcpy (q, curr_pathname, p - curr_pathname);
234 q[p - curr_pathname] = '\0';
235 curr_installdir = q;
236 }
237
238
239
240 {
241 const char *rp = rel_installdir + strlen (rel_installdir);
242 const char *cp = curr_installdir + strlen (curr_installdir);
243 const char *cp_base =
244 curr_installdir + FILE_SYSTEM_PREFIX_LEN (curr_installdir);
245
246 while (rp > rel_installdir && cp > cp_base)
247 {
248 bool same = false;
249 const char *rpi = rp;
250 const char *cpi = cp;
251
252 while (rpi > rel_installdir && cpi > cp_base)
253 {
254 rpi--;
255 cpi--;
256 if (ISSLASH (*rpi) || ISSLASH (*cpi))
257 {
258 if (ISSLASH (*rpi) && ISSLASH (*cpi))
259 same = true;
260 break;
261 }
262
263
264
265 #if defined _WIN32 || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
266
267 if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)
268 != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
269 break;
270 #else
271 if (*rpi != *cpi)
272 break;
273 #endif
274 }
275 if (!same)
276 break;
277
278
279 rp = rpi;
280 cp = cpi;
281 }
282
283 if (rp > rel_installdir)
284 {
285
286 free (curr_installdir);
287 return NULL;
288 }
289
290 {
291 size_t computed_curr_prefix_len = cp - curr_installdir;
292 char *computed_curr_prefix;
293
294 computed_curr_prefix = (char *) xmalloc (computed_curr_prefix_len + 1);
295 #ifdef NO_XMALLOC
296 if (computed_curr_prefix == NULL)
297 {
298 free (curr_installdir);
299 return NULL;
300 }
301 #endif
302 memcpy (computed_curr_prefix, curr_installdir, computed_curr_prefix_len);
303 computed_curr_prefix[computed_curr_prefix_len] = '\0';
304
305 free (curr_installdir);
306
307 return computed_curr_prefix;
308 }
309 }
310 }
311
312 #endif
313
314 #if defined PIC && defined INSTALLDIR && ENABLE_COSTLY_RELOCATABLE
315
316
317 static char *shared_library_fullname;
318
319 #if defined _WIN32 && !defined __CYGWIN__
320
321
322
323
324
325
326
327
328
329
330
331 BOOL WINAPI
332 DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
333 {
334 (void) reserved;
335
336 if (event == DLL_PROCESS_ATTACH)
337 {
338
339 static char location[MAX_PATH];
340
341 if (!GetModuleFileName (module_handle, location, sizeof (location)))
342
343 return FALSE;
344
345 if (!IS_FILE_NAME_WITH_DIR (location))
346
347 return FALSE;
348
349
350
351
352 if (!(shared_library_fullname != NULL
353 && strcmp (shared_library_fullname, location) == 0))
354
355 shared_library_fullname = strdup (location);
356 }
357
358 return TRUE;
359 }
360
361 #elif defined __EMX__
362
363 extern int _CRT_init (void);
364 extern void _CRT_term (void);
365 extern void __ctordtorInit (void);
366 extern void __ctordtorTerm (void);
367
368 unsigned long _System
369 _DLL_InitTerm (unsigned long hModule, unsigned long ulFlag)
370 {
371 static char location[CCHMAXPATH];
372
373 switch (ulFlag)
374 {
375 case 0:
376 if (_CRT_init () == -1)
377 return 0;
378
379 __ctordtorInit();
380
381
382
383 if (DosQueryModuleName (hModule, sizeof (location), location))
384 return 0;
385
386 _fnslashify (location);
387 shared_library_fullname = strdup (location);
388 break;
389
390 case 1:
391 __ctordtorTerm();
392
393 _CRT_term ();
394 break;
395 }
396
397 return 1;
398 }
399
400 #else
401
402 static void
403 find_shared_library_fullname ()
404 {
405 #if (defined __linux__ && (__GLIBC__ >= 2 || defined __UCLIBC__)) || defined __CYGWIN__
406
407
408
409
410
411 FILE *fp;
412
413
414 fp = fopen ("/proc/self/maps", "r");
415 if (fp)
416 {
417 unsigned long address = (unsigned long) &find_shared_library_fullname;
418 for (;;)
419 {
420 unsigned long start, end;
421 int c;
422
423 if (fscanf (fp, "%lx-%lx", &start, &end) != 2)
424 break;
425 if (address >= start && address <= end - 1)
426 {
427
428 while (c = getc (fp), c != EOF && c != '\n' && c != '/')
429 continue;
430 if (c == '/')
431 {
432 size_t size;
433 int len;
434
435 ungetc (c, fp);
436 shared_library_fullname = NULL; size = 0;
437 len = getline (&shared_library_fullname, &size, fp);
438 if (len >= 0)
439 {
440
441 if (len > 0 && shared_library_fullname[len - 1] == '\n')
442 shared_library_fullname[len - 1] = '\0';
443 }
444 }
445 break;
446 }
447 while (c = getc (fp), c != EOF && c != '\n')
448 continue;
449 }
450 fclose (fp);
451 }
452 #endif
453 }
454
455 #endif
456
457
458
459
460 static char *
461 get_shared_library_fullname ()
462 {
463 #if !(defined _WIN32 && !defined __CYGWIN__) && !defined __EMX__
464 static bool tried_find_shared_library_fullname;
465 if (!tried_find_shared_library_fullname)
466 {
467 find_shared_library_fullname ();
468 tried_find_shared_library_fullname = true;
469 }
470 #endif
471 return shared_library_fullname;
472 }
473
474 #endif
475
476
477
478
479
480 const char *
481 relocate (const char *pathname)
482 {
483 #if defined PIC && defined INSTALLDIR && ENABLE_COSTLY_RELOCATABLE
484 static int initialized;
485
486
487 if (!initialized)
488 {
489
490
491
492
493
494
495
496
497 const char *orig_installprefix = INSTALLPREFIX;
498 const char *orig_installdir = INSTALLDIR;
499 char *curr_prefix_better;
500
501 curr_prefix_better =
502 compute_curr_prefix (orig_installprefix, orig_installdir,
503 get_shared_library_fullname ());
504
505 set_relocation_prefix (orig_installprefix,
506 curr_prefix_better != NULL
507 ? curr_prefix_better
508 : curr_prefix);
509
510 if (curr_prefix_better != NULL)
511 free (curr_prefix_better);
512
513 initialized = 1;
514 }
515 #endif
516
517
518
519
520
521 if (orig_prefix != NULL && curr_prefix != NULL
522 && strncmp (pathname, orig_prefix, orig_prefix_len) == 0)
523 {
524 if (pathname[orig_prefix_len] == '\0')
525 {
526
527 char *result = (char *) xmalloc (strlen (curr_prefix) + 1);
528
529 #ifdef NO_XMALLOC
530 if (result != NULL)
531 #endif
532 {
533 strcpy (result, curr_prefix);
534 return result;
535 }
536 }
537 else if (ISSLASH (pathname[orig_prefix_len]))
538 {
539
540 const char *pathname_tail = &pathname[orig_prefix_len];
541 char *result =
542 (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1);
543
544 #ifdef NO_XMALLOC
545 if (result != NULL)
546 #endif
547 {
548 memcpy (result, curr_prefix, curr_prefix_len);
549 strcpy (result + curr_prefix_len, pathname_tail);
550 return result;
551 }
552 }
553 }
554
555 #ifdef __EMX__
556 # ifdef __KLIBC__
557 # undef strncmp
558
559 if (strncmp (pathname, "/@unixroot", 10) == 0
560 && (pathname[10] == '\0' || ISSLASH (pathname[10])))
561 {
562
563 return pathname;
564 }
565 else
566 # endif
567 if (ISSLASH (pathname[0]))
568 {
569 const char *unixroot = getenv ("UNIXROOT");
570
571 if (unixroot && HAS_DEVICE (unixroot) && unixroot[2] == '\0')
572 {
573 char *result = (char *) xmalloc (2 + strlen (pathname) + 1);
574 #ifdef NO_XMALLOC
575 if (result != NULL)
576 #endif
577 {
578 memcpy (result, unixroot, 2);
579 strcpy (result + 2, pathname);
580 return result;
581 }
582 }
583 }
584 #endif
585
586
587 return pathname;
588 }
589
590
591
592
593
594
595 const char *
596 relocate2 (const char *pathname, char **allocatedp)
597 {
598 const char *result = relocate (pathname);
599 *allocatedp = (result != pathname ? (char *) result : NULL);
600 return result;
601 }
602
603 #endif