OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [intl/] [relocatable.c] - Blame information for rev 321

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 22 khays
/* Provide relocatable packages.
2
   Copyright (C) 2003 Free Software Foundation, Inc.
3
   Written by Bruno Haible <bruno@clisp.org>, 2003.
4
 
5
   This program is free software; you can redistribute it and/or modify it
6
   under the terms of the GNU Library General Public License as published
7
   by the Free Software Foundation; either version 2, or (at your option)
8
   any later version.
9
 
10
   This program is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
   Library General Public License for more details.
14
 
15
   You should have received a copy of the GNU Library General Public
16
   License along with this program; if not, write to the Free Software
17
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
18
   USA.  */
19
 
20
 
21
/* Tell glibc's <stdio.h> to provide a prototype for getline().
22
   This must come before <config.h> because <config.h> may include
23
   <features.h>, and once <features.h> has been included, it's too late.  */
24
#ifndef _GNU_SOURCE
25
# define _GNU_SOURCE    1
26
#endif
27
 
28
#ifdef HAVE_CONFIG_H
29
# include "config.h"
30
#endif
31
 
32
/* Specification.  */
33
#include "relocatable.h"
34
 
35
#if ENABLE_RELOCATABLE
36
 
37
#include <stddef.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <string.h>
41
 
42
#ifdef NO_XMALLOC
43
# define xmalloc malloc
44
#else
45
# include "xmalloc.h"
46
#endif
47
 
48
#if DEPENDS_ON_LIBCHARSET
49
# include <libcharset.h>
50
#endif
51
#if DEPENDS_ON_LIBICONV && HAVE_ICONV
52
# include <iconv.h>
53
#endif
54
#if DEPENDS_ON_LIBINTL && ENABLE_NLS
55
# include <libintl.h>
56
#endif
57
 
58
/* Faked cheap 'bool'.  */
59
#undef bool
60
#undef false
61
#undef true
62
#define bool int
63
#define false 0
64
#define true 1
65
 
66
/* Pathname support.
67
   ISSLASH(C)           tests whether C is a directory separator character.
68
   IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
69
 */
70
#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
71
  /* Win32, OS/2, DOS */
72
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
73
# define HAS_DEVICE(P) \
74
    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
75
     && (P)[1] == ':')
76
# define IS_PATH_WITH_DIR(P) \
77
    (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
78
# define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
79
#else
80
  /* Unix */
81
# define ISSLASH(C) ((C) == '/')
82
# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
83
# define FILESYSTEM_PREFIX_LEN(P) 0
84
#endif
85
 
86
/* Original installation prefix.  */
87
static char *orig_prefix;
88
static size_t orig_prefix_len;
89
/* Current installation prefix.  */
90
static char *curr_prefix;
91
static size_t curr_prefix_len;
92
/* These prefixes do not end in a slash.  Anything that will be concatenated
93
   to them must start with a slash.  */
94
 
95
/* Sets the original and the current installation prefix of this module.
96
   Relocation simply replaces a pathname starting with the original prefix
97
   by the corresponding pathname with the current prefix instead.  Both
98
   prefixes should be directory names without trailing slash (i.e. use ""
99
   instead of "/").  */
100
static void
101
set_this_relocation_prefix (const char *orig_prefix_arg,
102
                            const char *curr_prefix_arg)
103
{
104
  if (orig_prefix_arg != NULL && curr_prefix_arg != NULL
105
      /* Optimization: if orig_prefix and curr_prefix are equal, the
106
         relocation is a nop.  */
107
      && strcmp (orig_prefix_arg, curr_prefix_arg) != 0)
108
    {
109
      /* Duplicate the argument strings.  */
110
      char *memory;
111
 
112
      orig_prefix_len = strlen (orig_prefix_arg);
113
      curr_prefix_len = strlen (curr_prefix_arg);
114
      memory = (char *) xmalloc (orig_prefix_len + 1 + curr_prefix_len + 1);
115
#ifdef NO_XMALLOC
116
      if (memory != NULL)
117
#endif
118
        {
119
          memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);
120
          orig_prefix = memory;
121
          memory += orig_prefix_len + 1;
122
          memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);
123
          curr_prefix = memory;
124
          return;
125
        }
126
    }
127
  orig_prefix = NULL;
128
  curr_prefix = NULL;
129
  /* Don't worry about wasted memory here - this function is usually only
130
     called once.  */
131
}
132
 
133
/* Sets the original and the current installation prefix of the package.
134
   Relocation simply replaces a pathname starting with the original prefix
135
   by the corresponding pathname with the current prefix instead.  Both
136
   prefixes should be directory names without trailing slash (i.e. use ""
137
   instead of "/").  */
138
void
139
set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg)
140
{
141
  set_this_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
142
 
143
  /* Now notify all dependent libraries.  */
144
#if DEPENDS_ON_LIBCHARSET
145
  libcharset_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
146
#endif
147
#if DEPENDS_ON_LIBICONV && HAVE_ICONV && _LIBICONV_VERSION >= 0x0109
148
  libiconv_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
149
#endif
150
#if DEPENDS_ON_LIBINTL && ENABLE_NLS && defined libintl_set_relocation_prefix
151
  libintl_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
152
#endif
153
}
154
 
155
/* Convenience function:
156
   Computes the current installation prefix, based on the original
157
   installation prefix, the original installation directory of a particular
158
   file, and the current pathname of this file.  Returns NULL upon failure.  */
159
#ifdef IN_LIBRARY
160
#define compute_curr_prefix local_compute_curr_prefix
161
static
162
#endif
163
const char *
164
compute_curr_prefix (const char *orig_installprefix,
165
                     const char *orig_installdir,
166
                     const char *curr_pathname)
167
{
168
  const char *curr_installdir;
169
  const char *rel_installdir;
170
 
171
  if (curr_pathname == NULL)
172
    return NULL;
173
 
174
  /* Determine the relative installation directory, relative to the prefix.
175
     This is simply the difference between orig_installprefix and
176
     orig_installdir.  */
177
  if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix))
178
      != 0)
179
    /* Shouldn't happen - nothing should be installed outside $(prefix).  */
180
    return NULL;
181
  rel_installdir = orig_installdir + strlen (orig_installprefix);
182
 
183
  /* Determine the current installation directory.  */
184
  {
185
    const char *p_base = curr_pathname + FILESYSTEM_PREFIX_LEN (curr_pathname);
186
    const char *p = curr_pathname + strlen (curr_pathname);
187
    char *q;
188
 
189
    while (p > p_base)
190
      {
191
        p--;
192
        if (ISSLASH (*p))
193
          break;
194
      }
195
 
196
    q = (char *) xmalloc (p - curr_pathname + 1);
197
#ifdef NO_XMALLOC
198
    if (q == NULL)
199
      return NULL;
200
#endif
201
    memcpy (q, curr_pathname, p - curr_pathname);
202
    q[p - curr_pathname] = '\0';
203
    curr_installdir = q;
204
  }
205
 
206
  /* Compute the current installation prefix by removing the trailing
207
     rel_installdir from it.  */
208
  {
209
    const char *rp = rel_installdir + strlen (rel_installdir);
210
    const char *cp = curr_installdir + strlen (curr_installdir);
211
    const char *cp_base =
212
      curr_installdir + FILESYSTEM_PREFIX_LEN (curr_installdir);
213
 
214
    while (rp > rel_installdir && cp > cp_base)
215
      {
216
        bool same = false;
217
        const char *rpi = rp;
218
        const char *cpi = cp;
219
 
220
        while (rpi > rel_installdir && cpi > cp_base)
221
          {
222
            rpi--;
223
            cpi--;
224
            if (ISSLASH (*rpi) || ISSLASH (*cpi))
225
              {
226
                if (ISSLASH (*rpi) && ISSLASH (*cpi))
227
                  same = true;
228
                break;
229
              }
230
#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
231
            /* Win32, OS/2, DOS - case insignificant filesystem */
232
            if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)
233
                != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
234
              break;
235
#else
236
            if (*rpi != *cpi)
237
              break;
238
#endif
239
          }
240
        if (!same)
241
          break;
242
        /* The last pathname component was the same.  opi and cpi now point
243
           to the slash before it.  */
244
        rp = rpi;
245
        cp = cpi;
246
      }
247
 
248
    if (rp > rel_installdir)
249
      /* Unexpected: The curr_installdir does not end with rel_installdir.  */
250
      return NULL;
251
 
252
    {
253
      size_t curr_prefix_len = cp - curr_installdir;
254
      char *curr_prefix;
255
 
256
      curr_prefix = (char *) xmalloc (curr_prefix_len + 1);
257
#ifdef NO_XMALLOC
258
      if (curr_prefix == NULL)
259
        return NULL;
260
#endif
261
      memcpy (curr_prefix, curr_installdir, curr_prefix_len);
262
      curr_prefix[curr_prefix_len] = '\0';
263
 
264
      return curr_prefix;
265
    }
266
  }
267
}
268
 
269
#if defined PIC && defined INSTALLDIR
270
 
271
/* Full pathname of shared library, or NULL.  */
272
static char *shared_library_fullname;
273
 
274
#if defined _WIN32 || defined __WIN32__
275
 
276
/* Determine the full pathname of the shared library when it is loaded.  */
277
 
278
BOOL WINAPI
279
DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
280
{
281
  (void) reserved;
282
 
283
  if (event == DLL_PROCESS_ATTACH)
284
    {
285
      /* The DLL is being loaded into an application's address range.  */
286
      static char location[MAX_PATH];
287
 
288
      if (!GetModuleFileName (module_handle, location, sizeof (location)))
289
        /* Shouldn't happen.  */
290
        return FALSE;
291
 
292
      if (!IS_PATH_WITH_DIR (location))
293
        /* Shouldn't happen.  */
294
        return FALSE;
295
 
296
      shared_library_fullname = strdup (location);
297
    }
298
 
299
  return TRUE;
300
}
301
 
302
#else /* Unix */
303
 
304
static void
305
find_shared_library_fullname ()
306
{
307
#ifdef __linux__
308
  FILE *fp;
309
 
310
  /* Open the current process' maps file.  It describes one VMA per line.  */
311
  fp = fopen ("/proc/self/maps", "r");
312
  if (fp)
313
    {
314
      unsigned long address = (unsigned long) &find_shared_library_fullname;
315
      for (;;)
316
        {
317
          unsigned long start, end;
318
          int c;
319
 
320
          if (fscanf (fp, "%lx-%lx", &start, &end) != 2)
321
            break;
322
          if (address >= start && address <= end - 1)
323
            {
324
              /* Found it.  Now see if this line contains a filename.  */
325
              while (c = getc (fp), c != EOF && c != '\n' && c != '/')
326
                continue;
327
              if (c == '/')
328
                {
329
                  size_t size;
330
                  int len;
331
 
332
                  ungetc (c, fp);
333
                  shared_library_fullname = NULL; size = 0;
334
                  len = getline (&shared_library_fullname, &size, fp);
335
                  if (len >= 0)
336
                    {
337
                      /* Success: filled shared_library_fullname.  */
338
                      if (len > 0 && shared_library_fullname[len - 1] == '\n')
339
                        shared_library_fullname[len - 1] = '\0';
340
                    }
341
                }
342
              break;
343
            }
344
          while (c = getc (fp), c != EOF && c != '\n')
345
            continue;
346
        }
347
      fclose (fp);
348
    }
349
#endif
350
}
351
 
352
#endif /* WIN32 / Unix */
353
 
354
/* Return the full pathname of the current shared library.
355
   Return NULL if unknown.
356
   Guaranteed to work only on Linux and Woe32.  */
357
static char *
358
get_shared_library_fullname ()
359
{
360
#if !(defined _WIN32 || defined __WIN32__)
361
  static bool tried_find_shared_library_fullname;
362
  if (!tried_find_shared_library_fullname)
363
    {
364
      find_shared_library_fullname ();
365
      tried_find_shared_library_fullname = true;
366
    }
367
#endif
368
  return shared_library_fullname;
369
}
370
 
371
#endif /* PIC */
372
 
373
/* Returns the pathname, relocated according to the current installation
374
   directory.  */
375
const char *
376
relocate (const char *pathname)
377
{
378
#if defined PIC && defined INSTALLDIR
379
  static int initialized;
380
 
381
  /* Initialization code for a shared library.  */
382
  if (!initialized)
383
    {
384
      /* At this point, orig_prefix and curr_prefix likely have already been
385
         set through the main program's set_program_name_and_installdir
386
         function.  This is sufficient in the case that the library has
387
         initially been installed in the same orig_prefix.  But we can do
388
         better, to also cover the cases that 1. it has been installed
389
         in a different prefix before being moved to orig_prefix and (later)
390
         to curr_prefix, 2. unlike the program, it has not moved away from
391
         orig_prefix.  */
392
      const char *orig_installprefix = INSTALLPREFIX;
393
      const char *orig_installdir = INSTALLDIR;
394
      const char *curr_prefix_better;
395
 
396
      curr_prefix_better =
397
        compute_curr_prefix (orig_installprefix, orig_installdir,
398
                             get_shared_library_fullname ());
399
      if (curr_prefix_better == NULL)
400
        curr_prefix_better = curr_prefix;
401
 
402
      set_relocation_prefix (orig_installprefix, curr_prefix_better);
403
 
404
      initialized = 1;
405
    }
406
#endif
407
 
408
  /* Note: It is not necessary to perform case insensitive comparison here,
409
     even for DOS-like filesystems, because the pathname argument was
410
     typically created from the same Makefile variable as orig_prefix came
411
     from.  */
412
  if (orig_prefix != NULL && curr_prefix != NULL
413
      && strncmp (pathname, orig_prefix, orig_prefix_len) == 0)
414
    {
415
      if (pathname[orig_prefix_len] == '\0')
416
        /* pathname equals orig_prefix.  */
417
        return curr_prefix;
418
      if (ISSLASH (pathname[orig_prefix_len]))
419
        {
420
          /* pathname starts with orig_prefix.  */
421
          const char *pathname_tail = &pathname[orig_prefix_len];
422
          char *result =
423
            (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1);
424
 
425
#ifdef NO_XMALLOC
426
          if (result != NULL)
427
#endif
428
            {
429
              memcpy (result, curr_prefix, curr_prefix_len);
430
              strcpy (result + curr_prefix_len, pathname_tail);
431
              return result;
432
            }
433
        }
434
    }
435
  /* Nothing to relocate.  */
436
  return pathname;
437
}
438
 
439
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.