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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [boehm-gc/] [dyn_load.c] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/*
2
 * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
3
 * Copyright (c) 1997 by Silicon Graphics.  All rights reserved.
4
 *
5
 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
6
 * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
7
 *
8
 * Permission is hereby granted to use or copy this program
9
 * for any purpose,  provided the above notices are retained on all copies.
10
 * Permission to modify the code and to distribute modified code is granted,
11
 * provided the above notices are retained, and a notice that the code was
12
 * modified is included with the above copyright notice.
13
 *
14
 * Original author: Bill Janssen
15
 * Heavily modified by Hans Boehm and others
16
 */
17
 
18
/*
19
 * This is incredibly OS specific code for tracking down data sections in
20
 * dynamic libraries.  There appears to be no way of doing this quickly
21
 * without groveling through undocumented data structures.  We would argue
22
 * that this is a bug in the design of the dlopen interface.  THIS CODE
23
 * MAY BREAK IN FUTURE OS RELEASES.  If this matters to you, don't hesitate
24
 * to let your vendor know ...
25
 *
26
 * None of this is safe with dlclose and incremental collection.
27
 * But then not much of anything is safe in the presence of dlclose.
28
 */
29
#if defined(__linux__) && !defined(_GNU_SOURCE)
30
    /* Can't test LINUX, since this must be define before other includes */
31
#   define _GNU_SOURCE
32
#endif
33
#if !defined(MACOS) && !defined(_WIN32_WCE)
34
#  include <sys/types.h>
35
#endif
36
#include "private/gc_priv.h"
37
 
38
/* BTL: avoid circular redefinition of dlopen if GC_SOLARIS_THREADS defined */
39
# if (defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS)) \
40
      && defined(dlopen) && !defined(GC_USE_LD_WRAP)
41
    /* To support threads in Solaris, gc.h interposes on dlopen by       */
42
    /* defining "dlopen" to be "GC_dlopen", which is implemented below.  */
43
    /* However, both GC_FirstDLOpenedLinkMap() and GC_dlopen() use the   */
44
    /* real system dlopen() in their implementation. We first remove     */
45
    /* gc.h's dlopen definition and restore it later, after GC_dlopen(). */
46
#   undef dlopen
47
#   define GC_must_restore_redefined_dlopen
48
# else
49
#   undef GC_must_restore_redefined_dlopen
50
# endif
51
 
52
#if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE)) \
53
    && !defined(PCR)
54
#if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && \
55
    !defined(MSWIN32) && !defined(MSWINCE) && \
56
    !(defined(ALPHA) && defined(OSF1)) && \
57
    !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \
58
    !defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \
59
    !(defined(FREEBSD) && defined(__ELF__)) && \
60
    !(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \
61
    !defined(DARWIN)
62
 --> We only know how to find data segments of dynamic libraries for the
63
 --> above.  Additional SVR4 variants might not be too
64
 --> hard to add.
65
#endif
66
 
67
#include <stdio.h>
68
#ifdef SUNOS5DL
69
#   include <sys/elf.h>
70
#   include <dlfcn.h>
71
#   include <link.h>
72
#endif
73
#ifdef SUNOS4
74
#   include <dlfcn.h>
75
#   include <link.h>
76
#   include <a.out.h>
77
  /* struct link_map field overrides */
78
#   define l_next       lm_next
79
#   define l_addr       lm_addr
80
#   define l_name       lm_name
81
#endif
82
 
83
#if defined(NETBSD)
84
#   include <machine/elf_machdep.h>
85
#   define ELFSIZE ARCH_ELFSIZE
86
#endif
87
 
88
#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
89
    (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
90
    (defined(NETBSD) && defined(__ELF__)) || defined(HURD)
91
#   include <stddef.h>
92
#   include <elf.h>
93
#   include <link.h>
94
#endif
95
 
96
/* Newer versions of GNU/Linux define this macro.  We
97
 * define it similarly for any ELF systems that don't.  */
98
#  ifndef ElfW
99
#    ifdef __NetBSD__
100
#      if ELFSIZE == 32
101
#        define ElfW(type) Elf32_##type
102
#      else
103
#        define ElfW(type) Elf64_##type
104
#      endif
105
#    else
106
#      if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
107
#        define ElfW(type) Elf32_##type
108
#      else
109
#        define ElfW(type) Elf64_##type
110
#      endif
111
#    endif
112
#  endif
113
 
114
#if defined(SUNOS5DL) && !defined(USE_PROC_FOR_LIBRARIES)
115
 
116
#ifdef LINT
117
    Elf32_Dyn _DYNAMIC;
118
#endif
119
 
120
static struct link_map *
121
GC_FirstDLOpenedLinkMap()
122
{
123
    extern ElfW(Dyn) _DYNAMIC;
124
    ElfW(Dyn) *dp;
125
    struct r_debug *r;
126
    static struct link_map * cachedResult = 0;
127
    static ElfW(Dyn) *dynStructureAddr = 0;
128
                        /* BTL: added to avoid Solaris 5.3 ld.so _DYNAMIC bug */
129
 
130
#   ifdef SUNOS53_SHARED_LIB
131
        /* BTL: Avoid the Solaris 5.3 bug that _DYNAMIC isn't being set */
132
        /* up properly in dynamically linked .so's. This means we have  */
133
        /* to use its value in the set of original object files loaded  */
134
        /* at program startup.                                          */
135
        if( dynStructureAddr == 0 ) {
136
          void* startupSyms = dlopen(0, RTLD_LAZY);
137
          dynStructureAddr = (ElfW(Dyn)*)dlsym(startupSyms, "_DYNAMIC");
138
                }
139
#   else
140
        dynStructureAddr = &_DYNAMIC;
141
#   endif
142
 
143
    if( dynStructureAddr == 0) {
144
        return(0);
145
    }
146
    if( cachedResult == 0 ) {
147
        int tag;
148
        for( dp = ((ElfW(Dyn) *)(&_DYNAMIC)); (tag = dp->d_tag) != 0; dp++ ) {
149
            if( tag == DT_DEBUG ) {
150
                struct link_map *lm
151
                        = ((struct r_debug *)(dp->d_un.d_ptr))->r_map;
152
                if( lm != 0 ) cachedResult = lm->l_next; /* might be NIL */
153
                break;
154
            }
155
        }
156
    }
157
    return cachedResult;
158
}
159
 
160
#endif /* SUNOS5DL ... */
161
 
162
/* BTL: added to fix circular dlopen definition if GC_SOLARIS_THREADS defined */
163
# if defined(GC_must_restore_redefined_dlopen)
164
#   define dlopen GC_dlopen
165
# endif
166
 
167
#if defined(SUNOS4) && !defined(USE_PROC_FOR_LIBRARIES)
168
 
169
#ifdef LINT
170
    struct link_dynamic _DYNAMIC;
171
#endif
172
 
173
static struct link_map *
174
GC_FirstDLOpenedLinkMap()
175
{
176
    extern struct link_dynamic _DYNAMIC;
177
 
178
    if( &_DYNAMIC == 0) {
179
        return(0);
180
    }
181
    return(_DYNAMIC.ld_un.ld_1->ld_loaded);
182
}
183
 
184
/* Return the address of the ld.so allocated common symbol      */
185
/* with the least address, or 0 if none.                        */
186
static ptr_t GC_first_common()
187
{
188
    ptr_t result = 0;
189
    extern struct link_dynamic _DYNAMIC;
190
    struct rtc_symb * curr_symbol;
191
 
192
    if( &_DYNAMIC == 0) {
193
        return(0);
194
    }
195
    curr_symbol = _DYNAMIC.ldd -> ldd_cp;
196
    for (; curr_symbol != 0; curr_symbol = curr_symbol -> rtc_next) {
197
        if (result == 0
198
            || (ptr_t)(curr_symbol -> rtc_sp -> n_value) < result) {
199
            result = (ptr_t)(curr_symbol -> rtc_sp -> n_value);
200
        }
201
    }
202
    return(result);
203
}
204
 
205
#endif  /* SUNOS4 ... */
206
 
207
# if defined(SUNOS4) || defined(SUNOS5DL)
208
/* Add dynamic library data sections to the root set.           */
209
# if !defined(PCR) && !defined(GC_SOLARIS_THREADS) && defined(THREADS)
210
#   ifndef SRC_M3
211
        --> fix mutual exclusion with dlopen
212
#   endif  /* We assume M3 programs don't call dlopen for now */
213
# endif
214
 
215
# ifndef USE_PROC_FOR_LIBRARIES
216
void GC_register_dynamic_libraries()
217
{
218
  struct link_map *lm = GC_FirstDLOpenedLinkMap();
219
 
220
 
221
  for (lm = GC_FirstDLOpenedLinkMap();
222
       lm != (struct link_map *) 0;  lm = lm->l_next)
223
    {
224
#     ifdef SUNOS4
225
        struct exec *e;
226
 
227
        e = (struct exec *) lm->lm_addr;
228
        GC_add_roots_inner(
229
                    ((char *) (N_DATOFF(*e) + lm->lm_addr)),
230
                    ((char *) (N_BSSADDR(*e) + e->a_bss + lm->lm_addr)),
231
                    TRUE);
232
#     endif
233
#     ifdef SUNOS5DL
234
        ElfW(Ehdr) * e;
235
        ElfW(Phdr) * p;
236
        unsigned long offset;
237
        char * start;
238
        register int i;
239
 
240
        e = (ElfW(Ehdr) *) lm->l_addr;
241
        p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff));
242
        offset = ((unsigned long)(lm->l_addr));
243
        for( i = 0; i < (int)(e->e_phnum); ((i++),(p++)) ) {
244
          switch( p->p_type ) {
245
            case PT_LOAD:
246
              {
247
                if( !(p->p_flags & PF_W) ) break;
248
                start = ((char *)(p->p_vaddr)) + offset;
249
                GC_add_roots_inner(
250
                  start,
251
                  start + p->p_memsz,
252
                  TRUE
253
                );
254
              }
255
              break;
256
            default:
257
              break;
258
          }
259
        }
260
#     endif
261
    }
262
#   ifdef SUNOS4
263
      {
264
        static ptr_t common_start = 0;
265
        ptr_t common_end;
266
        extern ptr_t GC_find_limit();
267
 
268
        if (common_start == 0) common_start = GC_first_common();
269
        if (common_start != 0) {
270
            common_end = GC_find_limit(common_start, TRUE);
271
            GC_add_roots_inner((char *)common_start, (char *)common_end, TRUE);
272
        }
273
      }
274
#   endif
275
}
276
 
277
# endif /* !USE_PROC ... */
278
# endif /* SUNOS */
279
 
280
#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
281
    (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
282
    (defined(NETBSD) && defined(__ELF__)) || defined(HURD)
283
 
284
 
285
#ifdef USE_PROC_FOR_LIBRARIES
286
 
287
#include <string.h>
288
 
289
#include <sys/stat.h>
290
#include <fcntl.h>
291
#include <unistd.h>
292
 
293
#define MAPS_BUF_SIZE (32*1024)
294
 
295
extern ssize_t GC_repeat_read(int fd, char *buf, size_t count);
296
        /* Repeatedly read until buffer is filled, or EOF is encountered */
297
        /* Defined in os_dep.c.                                          */
298
 
299
char *GC_parse_map_entry(char *buf_ptr, word *start, word *end,
300
                         char *prot_buf, unsigned int *maj_dev);
301
word GC_apply_to_maps(word (*fn)(char *));
302
        /* From os_dep.c        */
303
 
304
word GC_register_map_entries(char *maps)
305
{
306
    char prot_buf[5];
307
    char *buf_ptr = maps;
308
    int count;
309
    word start, end;
310
    unsigned int maj_dev;
311
    word least_ha, greatest_ha;
312
    unsigned i;
313
    word datastart = (word)(DATASTART);
314
 
315
    /* Compute heap bounds. FIXME: Should be done by add_to_heap?       */
316
        least_ha = (word)(-1);
317
        greatest_ha = 0;
318
        for (i = 0; i < GC_n_heap_sects; ++i) {
319
            word sect_start = (word)GC_heap_sects[i].hs_start;
320
            word sect_end = sect_start + GC_heap_sects[i].hs_bytes;
321
            if (sect_start < least_ha) least_ha = sect_start;
322
            if (sect_end > greatest_ha) greatest_ha = sect_end;
323
        }
324
        if (greatest_ha < (word)GC_scratch_last_end_ptr)
325
            greatest_ha = (word)GC_scratch_last_end_ptr;
326
 
327
    for (;;) {
328
        buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev);
329
        if (buf_ptr == NULL) return 1;
330
        if (prot_buf[1] == 'w') {
331
            /* This is a writable mapping.  Add it to           */
332
            /* the root set unless it is already otherwise      */
333
            /* accounted for.                                   */
334
            if (start <= (word)GC_stackbottom && end >= (word)GC_stackbottom) {
335
                /* Stack mapping; discard       */
336
                continue;
337
            }
338
#           ifdef THREADS
339
              if (GC_segment_is_thread_stack(start, end)) continue;
340
#           endif
341
            /* We no longer exclude the main data segment.              */
342
            if (start < least_ha && end > least_ha) {
343
                end = least_ha;
344
            }
345
            if (start < greatest_ha && end > greatest_ha) {
346
                start = greatest_ha;
347
            }
348
            if (start >= least_ha && end <= greatest_ha) continue;
349
            GC_add_roots_inner((char *)start, (char *)end, TRUE);
350
        }
351
    }
352
    return 1;
353
}
354
 
355
void GC_register_dynamic_libraries()
356
{
357
   if (!GC_apply_to_maps(GC_register_map_entries))
358
       ABORT("Failed to read /proc for library registration.");
359
}
360
 
361
/* We now take care of the main data segment ourselves: */
362
GC_bool GC_register_main_static_data()
363
{
364
  return FALSE;
365
}
366
 
367
# define HAVE_REGISTER_MAIN_STATIC_DATA
368
 
369
#endif /* USE_PROC_FOR_LIBRARIES */
370
 
371
#if !defined(USE_PROC_FOR_LIBRARIES)
372
/* The following is the preferred way to walk dynamic libraries */
373
/* For glibc 2.2.4+.  Unfortunately, it doesn't work for older  */
374
/* versions.  Thanks to Jakub Jelinek for most of the code.     */
375
 
376
# if defined(LINUX) /* Are others OK here, too? */ \
377
     && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
378
         || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
379
 
380
/* We have the header files for a glibc that includes dl_iterate_phdr.  */
381
/* It may still not be available in the library on the target system.   */
382
/* Thus we also treat it as a weak symbol.                              */
383
#define HAVE_DL_ITERATE_PHDR
384
 
385
static int GC_register_dynlib_callback(info, size, ptr)
386
     struct dl_phdr_info * info;
387
     size_t size;
388
     void * ptr;
389
{
390
  const ElfW(Phdr) * p;
391
  char * start;
392
  register int i;
393
 
394
  /* Make sure struct dl_phdr_info is at least as big as we need.  */
395
  if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
396
      + sizeof (info->dlpi_phnum))
397
    return -1;
398
 
399
  p = info->dlpi_phdr;
400
  for( i = 0; i < (int)(info->dlpi_phnum); ((i++),(p++)) ) {
401
    switch( p->p_type ) {
402
      case PT_LOAD:
403
        {
404
          if( !(p->p_flags & PF_W) ) break;
405
          start = ((char *)(p->p_vaddr)) + info->dlpi_addr;
406
          GC_add_roots_inner(start, start + p->p_memsz, TRUE);
407
        }
408
      break;
409
      default:
410
        break;
411
    }
412
  }
413
 
414
  * (int *)ptr = 1;     /* Signal that we were called */
415
  return 0;
416
}
417
 
418
/* Return TRUE if we succeed, FALSE if dl_iterate_phdr wasn't there. */
419
 
420
#pragma weak dl_iterate_phdr
421
 
422
GC_bool GC_register_dynamic_libraries_dl_iterate_phdr()
423
{
424
  if (dl_iterate_phdr) {
425
    int did_something = 0;
426
    dl_iterate_phdr(GC_register_dynlib_callback, &did_something);
427
    if (!did_something) {
428
        /* dl_iterate_phdr may forget the static data segment in        */
429
        /* statically linked executables.                               */
430
        GC_add_roots_inner(DATASTART, (char *)(DATAEND), TRUE);
431
#       if defined(DATASTART2)
432
          GC_add_roots_inner(DATASTART2, (char *)(DATAEND2), TRUE);
433
#       endif
434
    }
435
 
436
    return TRUE;
437
  } else {
438
    return FALSE;
439
  }
440
}
441
 
442
/* Do we need to separately register the main static data segment? */
443
GC_bool GC_register_main_static_data()
444
{
445
  return (dl_iterate_phdr == 0);
446
}
447
 
448
#define HAVE_REGISTER_MAIN_STATIC_DATA
449
 
450
# else /* !LINUX || version(glibc) < 2.2.4 */
451
 
452
/* Dynamic loading code for Linux running ELF. Somewhat tested on
453
 * Linux/x86, untested but hopefully should work on Linux/Alpha.
454
 * This code was derived from the Solaris/ELF support. Thanks to
455
 * whatever kind soul wrote that.  - Patrick Bridges */
456
 
457
/* This doesn't necessarily work in all cases, e.g. with preloaded
458
 * dynamic libraries.                                           */
459
 
460
#if defined(NETBSD)
461
#  include <sys/exec_elf.h>
462
/* for compatibility with 1.4.x */
463
#  ifndef DT_DEBUG
464
#  define DT_DEBUG     21
465
#  endif
466
#  ifndef PT_LOAD
467
#  define PT_LOAD      1
468
#  endif
469
#  ifndef PF_W
470
#  define PF_W         2
471
#  endif
472
#else
473
#  include <elf.h>
474
#endif
475
#include <link.h>
476
 
477
# endif
478
 
479
#ifdef __GNUC__
480
# pragma weak _DYNAMIC
481
#endif
482
extern ElfW(Dyn) _DYNAMIC[];
483
 
484
static struct link_map *
485
GC_FirstDLOpenedLinkMap()
486
{
487
    ElfW(Dyn) *dp;
488
    struct r_debug *r;
489
    static struct link_map *cachedResult = 0;
490
 
491
    if( _DYNAMIC == 0) {
492
        return(0);
493
    }
494
    if( cachedResult == 0 ) {
495
        int tag;
496
        for( dp = _DYNAMIC; (tag = dp->d_tag) != 0; dp++ ) {
497
            if( tag == DT_DEBUG ) {
498
                struct link_map *lm
499
                        = ((struct r_debug *)(dp->d_un.d_ptr))->r_map;
500
                if( lm != 0 ) cachedResult = lm->l_next; /* might be NIL */
501
                break;
502
            }
503
        }
504
    }
505
    return cachedResult;
506
}
507
 
508
 
509
void GC_register_dynamic_libraries()
510
{
511
  struct link_map *lm;
512
 
513
 
514
# ifdef HAVE_DL_ITERATE_PHDR
515
    if (GC_register_dynamic_libraries_dl_iterate_phdr()) {
516
        return;
517
    }
518
# endif
519
  lm = GC_FirstDLOpenedLinkMap();
520
  for (lm = GC_FirstDLOpenedLinkMap();
521
       lm != (struct link_map *) 0;  lm = lm->l_next)
522
    {
523
        ElfW(Ehdr) * e;
524
        ElfW(Phdr) * p;
525
        unsigned long offset;
526
        char * start;
527
        register int i;
528
 
529
        e = (ElfW(Ehdr) *) lm->l_addr;
530
        p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff));
531
        offset = ((unsigned long)(lm->l_addr));
532
        for( i = 0; i < (int)(e->e_phnum); ((i++),(p++)) ) {
533
          switch( p->p_type ) {
534
            case PT_LOAD:
535
              {
536
                if( !(p->p_flags & PF_W) ) break;
537
                start = ((char *)(p->p_vaddr)) + offset;
538
                GC_add_roots_inner(start, start + p->p_memsz, TRUE);
539
              }
540
              break;
541
            default:
542
              break;
543
          }
544
        }
545
    }
546
}
547
 
548
#endif /* !USE_PROC_FOR_LIBRARIES */
549
 
550
#endif /* LINUX */
551
 
552
#if defined(IRIX5) || (defined(USE_PROC_FOR_LIBRARIES) && !defined(LINUX))
553
 
554
#include <sys/procfs.h>
555
#include <sys/stat.h>
556
#include <fcntl.h>
557
#include <elf.h>
558
#include <errno.h>
559
#include <signal.h>  /* Only for the following test. */
560
#ifndef _sigargs
561
# define IRIX6
562
#endif
563
 
564
extern void * GC_roots_present();
565
        /* The type is a lie, since the real type doesn't make sense here, */
566
        /* and we only test for NULL.                                      */
567
 
568
 
569
/* We use /proc to track down all parts of the address space that are   */
570
/* mapped by the process, and throw out regions we know we shouldn't    */
571
/* worry about.  This may also work under other SVR4 variants.          */
572
void GC_register_dynamic_libraries()
573
{
574
    static int fd = -1;
575
    char buf[30];
576
    static prmap_t * addr_map = 0;
577
    static int current_sz = 0;   /* Number of records currently in addr_map */
578
    static int needed_sz;       /* Required size of addr_map            */
579
    register int i;
580
    register long flags;
581
    register ptr_t start;
582
    register ptr_t limit;
583
    ptr_t heap_start = (ptr_t)HEAP_START;
584
    ptr_t heap_end = heap_start;
585
 
586
#   ifdef SUNOS5DL
587
#     define MA_PHYS 0
588
#   endif /* SUNOS5DL */
589
 
590
    if (fd < 0) {
591
      sprintf(buf, "/proc/%d", getpid());
592
        /* The above generates a lint complaint, since pid_t varies.    */
593
        /* It's unclear how to improve this.                            */
594
      fd = open(buf, O_RDONLY);
595
      if (fd < 0) {
596
        ABORT("/proc open failed");
597
      }
598
    }
599
    if (ioctl(fd, PIOCNMAP, &needed_sz) < 0) {
600
        GC_err_printf2("fd = %d, errno = %d\n", fd, errno);
601
        ABORT("/proc PIOCNMAP ioctl failed");
602
    }
603
    if (needed_sz >= current_sz) {
604
        current_sz = needed_sz * 2 + 1;
605
                        /* Expansion, plus room for 0 record */
606
        addr_map = (prmap_t *)GC_scratch_alloc((word)
607
                                                (current_sz * sizeof(prmap_t)));
608
    }
609
    if (ioctl(fd, PIOCMAP, addr_map) < 0) {
610
        GC_err_printf4("fd = %d, errno = %d, needed_sz = %d, addr_map = 0x%X\n",
611
                        fd, errno, needed_sz, addr_map);
612
        ABORT("/proc PIOCMAP ioctl failed");
613
    };
614
    if (GC_n_heap_sects > 0) {
615
        heap_end = GC_heap_sects[GC_n_heap_sects-1].hs_start
616
                        + GC_heap_sects[GC_n_heap_sects-1].hs_bytes;
617
        if (heap_end < GC_scratch_last_end_ptr) heap_end = GC_scratch_last_end_ptr;
618
    }
619
    for (i = 0; i < needed_sz; i++) {
620
        flags = addr_map[i].pr_mflags;
621
        if ((flags & (MA_BREAK | MA_STACK | MA_PHYS)) != 0) goto irrelevant;
622
        if ((flags & (MA_READ | MA_WRITE)) != (MA_READ | MA_WRITE))
623
            goto irrelevant;
624
          /* The latter test is empirically useless in very old Irix    */
625
          /* versions.  Other than the                                  */
626
          /* main data and stack segments, everything appears to be     */
627
          /* mapped readable, writable, executable, and shared(!!).     */
628
          /* This makes no sense to me. - HB                            */
629
        start = (ptr_t)(addr_map[i].pr_vaddr);
630
        if (GC_roots_present(start)) goto irrelevant;
631
        if (start < heap_end && start >= heap_start)
632
                goto irrelevant;
633
#       ifdef MMAP_STACKS
634
          if (GC_is_thread_stack(start)) goto irrelevant;
635
#       endif /* MMAP_STACKS */
636
 
637
        limit = start + addr_map[i].pr_size;
638
        /* The following seemed to be necessary for very old versions   */
639
        /* of Irix, but it has been reported to discard relevant        */
640
        /* segments under Irix 6.5.                                     */
641
#       ifndef IRIX6
642
          if (addr_map[i].pr_off == 0 && strncmp(start, ELFMAG, 4) == 0) {
643
            /* Discard text segments, i.e. 0-offset mappings against    */
644
            /* executable files which appear to have ELF headers.       */
645
            caddr_t arg;
646
            int obj;
647
#           define MAP_IRR_SZ 10
648
            static ptr_t map_irr[MAP_IRR_SZ];
649
                                        /* Known irrelevant map entries */
650
            static int n_irr = 0;
651
            struct stat buf;
652
            register int i;
653
 
654
            for (i = 0; i < n_irr; i++) {
655
                if (map_irr[i] == start) goto irrelevant;
656
            }
657
            arg = (caddr_t)start;
658
            obj = ioctl(fd, PIOCOPENM, &arg);
659
            if (obj >= 0) {
660
                fstat(obj, &buf);
661
                close(obj);
662
                if ((buf.st_mode & 0111) != 0) {
663
                    if (n_irr < MAP_IRR_SZ) {
664
                        map_irr[n_irr++] = start;
665
                    }
666
                    goto irrelevant;
667
                }
668
            }
669
          }
670
#       endif /* !IRIX6 */
671
        GC_add_roots_inner(start, limit, TRUE);
672
      irrelevant: ;
673
    }
674
    /* Dont keep cached descriptor, for now.  Some kernels don't like us */
675
    /* to keep a /proc file descriptor around during kill -9.            */
676
        if (close(fd) < 0) ABORT("Couldnt close /proc file");
677
        fd = -1;
678
}
679
 
680
# endif /* USE_PROC || IRIX5 */
681
 
682
# if defined(MSWIN32) || defined(MSWINCE)
683
 
684
# define WIN32_LEAN_AND_MEAN
685
# define NOSERVICE
686
# include <windows.h>
687
# include <stdlib.h>
688
 
689
  /* We traverse the entire address space and register all segments     */
690
  /* that could possibly have been written to.                          */
691
 
692
  extern GC_bool GC_is_heap_base (ptr_t p);
693
 
694
# ifdef GC_WIN32_THREADS
695
    extern void GC_get_next_stack(char *start, char **lo, char **hi);
696
    void GC_cond_add_roots(char *base, char * limit)
697
    {
698
      char * curr_base = base;
699
      char * next_stack_lo;
700
      char * next_stack_hi;
701
 
702
      if (base == limit) return;
703
      for(;;) {
704
          GC_get_next_stack(curr_base, &next_stack_lo, &next_stack_hi);
705
          if (next_stack_lo >= limit) break;
706
          GC_add_roots_inner(curr_base, next_stack_lo, TRUE);
707
          curr_base = next_stack_hi;
708
      }
709
      if (curr_base < limit) GC_add_roots_inner(curr_base, limit, TRUE);
710
    }
711
# else
712
    void GC_cond_add_roots(char *base, char * limit)
713
    {
714
      char dummy;
715
      char * stack_top
716
         = (char *) ((word)(&dummy) & ~(GC_sysinfo.dwAllocationGranularity-1));
717
      if (base == limit) return;
718
      if (limit > stack_top && base < GC_stackbottom) {
719
          /* Part of the stack; ignore it. */
720
          return;
721
      }
722
      GC_add_roots_inner(base, limit, TRUE);
723
    }
724
# endif
725
 
726
# ifdef MSWINCE
727
  /* Do we need to separately register the main static data segment? */
728
  GC_bool GC_register_main_static_data()
729
  {
730
    return FALSE;
731
  }
732
# else /* win32 */
733
  extern GC_bool GC_no_win32_dlls;
734
 
735
  GC_bool GC_register_main_static_data()
736
  {
737
    return GC_no_win32_dlls;
738
  }
739
# endif /* win32 */
740
 
741
# define HAVE_REGISTER_MAIN_STATIC_DATA
742
 
743
  /* The frame buffer testing code is dead in this version.     */
744
  /* We leave it here temporarily in case the switch to just    */
745
  /* testing for MEM_IMAGE sections causes un expected          */
746
  /* problems.                                                  */
747
  GC_bool GC_warn_fb = TRUE;    /* Warn about traced likely     */
748
                                /* graphics memory.             */
749
  GC_bool GC_disallow_ignore_fb = FALSE;
750
  int GC_ignore_fb_mb;  /* Ignore mappings bigger than the      */
751
                        /* specified number of MB.              */
752
  GC_bool GC_ignore_fb = FALSE; /* Enable frame buffer  */
753
                                /* checking.            */
754
 
755
  /* Issue warning if tracing apparent framebuffer.             */
756
  /* This limits us to one warning, and it's a back door to     */
757
  /* disable that.                                              */
758
 
759
  /* Should [start, start+len) be treated as a frame buffer     */
760
  /* and ignored?                                               */
761
  /* Unfortunately, we currently have no real way to tell       */
762
  /* automatically, and rely largely on user input.             */
763
  /* FIXME: If we had more data on this phenomenon (e.g.        */
764
  /* is start aligned to a MB multiple?) we should be able to   */
765
  /* do better.                                                 */
766
  /* Based on a very limited sample, it appears that:           */
767
  /*    - Frame buffer mappings appear as mappings of length    */
768
  /*      2**n MB - 192K.  (We guess the 192K can vary a bit.)  */
769
  /*    - Have a stating address at best 64K aligned.           */
770
  /* I'd love more information about the mapping, since I       */
771
  /* can't reproduce the problem.                               */
772
  static GC_bool is_frame_buffer(ptr_t start, size_t len)
773
  {
774
    static GC_bool initialized = FALSE;
775
#   define MB (1024*1024)
776
#   define DEFAULT_FB_MB 15
777
#   define MIN_FB_MB 3
778
 
779
    if (GC_disallow_ignore_fb) return FALSE;
780
    if (!initialized) {
781
      char * ignore_fb_string =  GETENV("GC_IGNORE_FB");
782
 
783
      if (0 != ignore_fb_string) {
784
        while (*ignore_fb_string == ' ' || *ignore_fb_string == '\t')
785
          ++ignore_fb_string;
786
        if (*ignore_fb_string == '\0') {
787
          GC_ignore_fb_mb = DEFAULT_FB_MB;
788
        } else {
789
          GC_ignore_fb_mb = atoi(ignore_fb_string);
790
          if (GC_ignore_fb_mb < MIN_FB_MB) {
791
            WARN("Bad GC_IGNORE_FB value.  Using %ld\n", DEFAULT_FB_MB);
792
            GC_ignore_fb_mb = DEFAULT_FB_MB;
793
          }
794
        }
795
        GC_ignore_fb = TRUE;
796
      } else {
797
        GC_ignore_fb_mb = DEFAULT_FB_MB;  /* For warning */
798
      }
799
      initialized = TRUE;
800
    }
801
    if (len >= ((size_t)GC_ignore_fb_mb << 20)) {
802
      if (GC_ignore_fb) {
803
        return TRUE;
804
      } else {
805
        if (GC_warn_fb) {
806
          WARN("Possible frame buffer mapping at 0x%lx: \n"
807
               "\tConsider setting GC_IGNORE_FB to improve performance.\n",
808
               start);
809
          GC_warn_fb = FALSE;
810
        }
811
        return FALSE;
812
      }
813
    } else {
814
      return FALSE;
815
    }
816
  }
817
 
818
# ifdef DEBUG_VIRTUALQUERY
819
  void GC_dump_meminfo(MEMORY_BASIC_INFORMATION *buf)
820
  {
821
    GC_printf4("BaseAddress = %lx, AllocationBase = %lx, RegionSize = %lx(%lu)\n",
822
               buf -> BaseAddress, buf -> AllocationBase, buf -> RegionSize,
823
               buf -> RegionSize);
824
    GC_printf4("\tAllocationProtect = %lx, State = %lx, Protect = %lx, "
825
               "Type = %lx\n",
826
               buf -> AllocationProtect, buf -> State, buf -> Protect,
827
               buf -> Type);
828
  }
829
# endif /* DEBUG_VIRTUALQUERY */
830
 
831
  void GC_register_dynamic_libraries()
832
  {
833
    MEMORY_BASIC_INFORMATION buf;
834
    DWORD result;
835
    DWORD protect;
836
    LPVOID p;
837
    char * base;
838
    char * limit, * new_limit;
839
 
840
#   ifdef MSWIN32
841
      if (GC_no_win32_dlls) return;
842
#   endif
843
    base = limit = p = GC_sysinfo.lpMinimumApplicationAddress;
844
#   if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION)
845
    /* Only the first 32 MB of address space belongs to the current process */
846
    while (p < (LPVOID)0x02000000) {
847
        result = VirtualQuery(p, &buf, sizeof(buf));
848
        if (result == 0) {
849
            /* Page is free; advance to the next possible allocation base */
850
            new_limit = (char *)
851
                (((DWORD) p + GC_sysinfo.dwAllocationGranularity)
852
                 & ~(GC_sysinfo.dwAllocationGranularity-1));
853
        } else
854
#   else
855
    while (p < GC_sysinfo.lpMaximumApplicationAddress) {
856
        result = VirtualQuery(p, &buf, sizeof(buf));
857
#   endif
858
        {
859
            if (result != sizeof(buf)) {
860
                ABORT("Weird VirtualQuery result");
861
            }
862
            new_limit = (char *)p + buf.RegionSize;
863
            protect = buf.Protect;
864
            if (buf.State == MEM_COMMIT
865
                && (protect == PAGE_EXECUTE_READWRITE
866
                    || protect == PAGE_READWRITE)
867
                && !GC_is_heap_base(buf.AllocationBase)
868
                /* This used to check for
869
                 * !is_frame_buffer(p, buf.RegionSize, buf.Type)
870
                 * instead of just checking for MEM_IMAGE.
871
                 * If something breaks, change it back. */
872
                && buf.Type == MEM_IMAGE) {
873
#               ifdef DEBUG_VIRTUALQUERY
874
                  GC_dump_meminfo(&buf);
875
#               endif
876
                if ((char *)p != limit) {
877
                    GC_cond_add_roots(base, limit);
878
                    base = p;
879
                }
880
                limit = new_limit;
881
            }
882
        }
883
        if (p > (LPVOID)new_limit /* overflow */) break;
884
        p = (LPVOID)new_limit;
885
    }
886
    GC_cond_add_roots(base, limit);
887
  }
888
 
889
#endif /* MSWIN32 || MSWINCE */
890
 
891
#if defined(ALPHA) && defined(OSF1)
892
 
893
#include <loader.h>
894
 
895
void GC_register_dynamic_libraries()
896
{
897
  int status;
898
  ldr_process_t mypid;
899
 
900
  /* module */
901
    ldr_module_t moduleid = LDR_NULL_MODULE;
902
    ldr_module_info_t moduleinfo;
903
    size_t moduleinfosize = sizeof(moduleinfo);
904
    size_t modulereturnsize;
905
 
906
  /* region */
907
    ldr_region_t region;
908
    ldr_region_info_t regioninfo;
909
    size_t regioninfosize = sizeof(regioninfo);
910
    size_t regionreturnsize;
911
 
912
  /* Obtain id of this process */
913
    mypid = ldr_my_process();
914
 
915
  /* For each module */
916
    while (TRUE) {
917
 
918
      /* Get the next (first) module */
919
        status = ldr_next_module(mypid, &moduleid);
920
 
921
      /* Any more modules? */
922
        if (moduleid == LDR_NULL_MODULE)
923
            break;    /* No more modules */
924
 
925
      /* Check status AFTER checking moduleid because */
926
      /* of a bug in the non-shared ldr_next_module stub */
927
        if (status != 0 ) {
928
            GC_printf1("dynamic_load: status = %ld\n", (long)status);
929
            {
930
                extern char *sys_errlist[];
931
                extern int sys_nerr;
932
                extern int errno;
933
                if (errno <= sys_nerr) {
934
                    GC_printf1("dynamic_load: %s\n", (long)sys_errlist[errno]);
935
               } else {
936
                    GC_printf1("dynamic_load: %d\n", (long)errno);
937
                }
938
        }
939
            ABORT("ldr_next_module failed");
940
         }
941
 
942
      /* Get the module information */
943
        status = ldr_inq_module(mypid, moduleid, &moduleinfo,
944
                                moduleinfosize, &modulereturnsize);
945
        if (status != 0 )
946
            ABORT("ldr_inq_module failed");
947
 
948
      /* is module for the main program (i.e. nonshared portion)? */
949
          if (moduleinfo.lmi_flags & LDR_MAIN)
950
              continue;    /* skip the main module */
951
 
952
#     ifdef VERBOSE
953
          GC_printf("---Module---\n");
954
          GC_printf("Module ID            = %16ld\n", moduleinfo.lmi_modid);
955
          GC_printf("Count of regions     = %16d\n", moduleinfo.lmi_nregion);
956
          GC_printf("flags for module     = %16lx\n", moduleinfo.lmi_flags);
957
          GC_printf("pathname of module   = \"%s\"\n", moduleinfo.lmi_name);
958
#     endif
959
 
960
      /* For each region in this module */
961
        for (region = 0; region < moduleinfo.lmi_nregion; region++) {
962
 
963
          /* Get the region information */
964
            status = ldr_inq_region(mypid, moduleid, region, &regioninfo,
965
                                    regioninfosize, &regionreturnsize);
966
            if (status != 0 )
967
                ABORT("ldr_inq_region failed");
968
 
969
          /* only process writable (data) regions */
970
            if (! (regioninfo.lri_prot & LDR_W))
971
                continue;
972
 
973
#         ifdef VERBOSE
974
              GC_printf("--- Region ---\n");
975
              GC_printf("Region number    = %16ld\n",
976
                        regioninfo.lri_region_no);
977
              GC_printf("Protection flags = %016x\n",  regioninfo.lri_prot);
978
              GC_printf("Virtual address  = %16p\n",   regioninfo.lri_vaddr);
979
              GC_printf("Mapped address   = %16p\n",   regioninfo.lri_mapaddr);
980
              GC_printf("Region size      = %16ld\n",  regioninfo.lri_size);
981
              GC_printf("Region name      = \"%s\"\n", regioninfo.lri_name);
982
#         endif
983
 
984
          /* register region as a garbage collection root */
985
            GC_add_roots_inner (
986
                (char *)regioninfo.lri_mapaddr,
987
                (char *)regioninfo.lri_mapaddr + regioninfo.lri_size,
988
                TRUE);
989
 
990
        }
991
    }
992
}
993
#endif
994
 
995
#if defined(HPUX)
996
 
997
#include <errno.h>
998
#include <dl.h>
999
 
1000
extern int errno;
1001
extern char *sys_errlist[];
1002
extern int sys_nerr;
1003
 
1004
void GC_register_dynamic_libraries()
1005
{
1006
  int status;
1007
  int index = 1; /* Ordinal position in shared library search list */
1008
  struct shl_descriptor *shl_desc; /* Shared library info, see dl.h */
1009
 
1010
  /* For each dynamic library loaded */
1011
    while (TRUE) {
1012
 
1013
      /* Get info about next shared library */
1014
        status = shl_get(index, &shl_desc);
1015
 
1016
      /* Check if this is the end of the list or if some error occured */
1017
        if (status != 0) {
1018
#        ifdef GC_HPUX_THREADS
1019
           /* I've seen errno values of 0.  The man page is not clear   */
1020
           /* as to whether errno should get set on a -1 return.        */
1021
           break;
1022
#        else
1023
          if (errno == EINVAL) {
1024
              break; /* Moved past end of shared library list --> finished */
1025
          } else {
1026
              if (errno <= sys_nerr) {
1027
                    GC_printf1("dynamic_load: %s\n", (long) sys_errlist[errno]);
1028
              } else {
1029
                    GC_printf1("dynamic_load: %d\n", (long) errno);
1030
              }
1031
              ABORT("shl_get failed");
1032
          }
1033
#        endif
1034
        }
1035
 
1036
#     ifdef VERBOSE
1037
          GC_printf0("---Shared library---\n");
1038
          GC_printf1("\tfilename        = \"%s\"\n", shl_desc->filename);
1039
          GC_printf1("\tindex           = %d\n", index);
1040
          GC_printf1("\thandle          = %08x\n",
1041
                                        (unsigned long) shl_desc->handle);
1042
          GC_printf1("\ttext seg. start = %08x\n", shl_desc->tstart);
1043
          GC_printf1("\ttext seg. end   = %08x\n", shl_desc->tend);
1044
          GC_printf1("\tdata seg. start = %08x\n", shl_desc->dstart);
1045
          GC_printf1("\tdata seg. end   = %08x\n", shl_desc->dend);
1046
          GC_printf1("\tref. count      = %lu\n", shl_desc->ref_count);
1047
#     endif
1048
 
1049
      /* register shared library's data segment as a garbage collection root */
1050
        GC_add_roots_inner((char *) shl_desc->dstart,
1051
                           (char *) shl_desc->dend, TRUE);
1052
 
1053
        index++;
1054
    }
1055
}
1056
#endif /* HPUX */
1057
 
1058
#ifdef RS6000
1059
#pragma alloca
1060
#include <sys/ldr.h>
1061
#include <sys/errno.h>
1062
void GC_register_dynamic_libraries()
1063
{
1064
        int len;
1065
        char *ldibuf;
1066
        int ldibuflen;
1067
        struct ld_info *ldi;
1068
 
1069
        ldibuf = alloca(ldibuflen = 8192);
1070
 
1071
        while ( (len = loadquery(L_GETINFO,ldibuf,ldibuflen)) < 0) {
1072
                if (errno != ENOMEM) {
1073
                        ABORT("loadquery failed");
1074
                }
1075
                ldibuf = alloca(ldibuflen *= 2);
1076
        }
1077
 
1078
        ldi = (struct ld_info *)ldibuf;
1079
        while (ldi) {
1080
                len = ldi->ldinfo_next;
1081
                GC_add_roots_inner(
1082
                                ldi->ldinfo_dataorg,
1083
                                (ptr_t)(unsigned long)ldi->ldinfo_dataorg
1084
                                + ldi->ldinfo_datasize,
1085
                                TRUE);
1086
                ldi = len ? (struct ld_info *)((char *)ldi + len) : 0;
1087
        }
1088
}
1089
#endif /* RS6000 */
1090
 
1091
#ifdef DARWIN
1092
 
1093
/* __private_extern__ hack required for pre-3.4 gcc versions.   */
1094
#ifndef __private_extern__
1095
# define __private_extern__ extern
1096
# include <mach-o/dyld.h>
1097
# undef __private_extern__
1098
#else
1099
# include <mach-o/dyld.h>
1100
#endif
1101
#include <mach-o/getsect.h>
1102
 
1103
/*#define DARWIN_DEBUG*/
1104
 
1105
const static struct {
1106
        const char *seg;
1107
        const char *sect;
1108
} GC_dyld_sections[] = {
1109
        { SEG_DATA, SECT_DATA },
1110
        { SEG_DATA, SECT_BSS },
1111
        { SEG_DATA, SECT_COMMON }
1112
};
1113
 
1114
#ifdef DARWIN_DEBUG
1115
static const char *GC_dyld_name_for_hdr(struct mach_header *hdr) {
1116
    unsigned long i,c;
1117
    c = _dyld_image_count();
1118
    for(i=0;i<c;i++) if(_dyld_get_image_header(i) == hdr)
1119
        return _dyld_get_image_name(i);
1120
    return NULL;
1121
}
1122
#endif
1123
 
1124
/* This should never be called by a thread holding the lock */
1125
static void GC_dyld_image_add(struct mach_header* hdr, unsigned long slide) {
1126
    unsigned long start,end,i;
1127
    const struct section *sec;
1128
    for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
1129
        sec = getsectbynamefromheader(
1130
            hdr,GC_dyld_sections[i].seg,GC_dyld_sections[i].sect);
1131
            if(sec == NULL || sec->size == 0) continue;
1132
            start = slide + sec->addr;
1133
            end = start + sec->size;
1134
#               ifdef DARWIN_DEBUG
1135
                GC_printf4("Adding section at %p-%p (%lu bytes) from image %s\n",
1136
                start,end,sec->size,GC_dyld_name_for_hdr(hdr));
1137
#                       endif
1138
        GC_add_roots((char*)start,(char*)end);
1139
        }
1140
#       ifdef DARWIN_DEBUG
1141
    GC_print_static_roots();
1142
#       endif
1143
}
1144
 
1145
/* This should never be called by a thread holding the lock */
1146
static void GC_dyld_image_remove(struct mach_header* hdr, unsigned long slide) {
1147
    unsigned long start,end,i;
1148
    const struct section *sec;
1149
    for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
1150
        sec = getsectbynamefromheader(
1151
            hdr,GC_dyld_sections[i].seg,GC_dyld_sections[i].sect);
1152
        if(sec == NULL || sec->size == 0) continue;
1153
        start = slide + sec->addr;
1154
        end = start + sec->size;
1155
#               ifdef DARWIN_DEBUG
1156
            GC_printf4("Removing section at %p-%p (%lu bytes) from image %s\n",
1157
                start,end,sec->size,GC_dyld_name_for_hdr(hdr));
1158
#               endif
1159
        GC_remove_roots((char*)start,(char*)end);
1160
    }
1161
#       ifdef DARWIN_DEBUG
1162
    GC_print_static_roots();
1163
#       endif
1164
}
1165
 
1166
void GC_register_dynamic_libraries() {
1167
    /* Currently does nothing. The callbacks are setup by GC_init_dyld()
1168
    The dyld library takes it from there. */
1169
}
1170
 
1171
/* The _dyld_* functions have an internal lock so no _dyld functions
1172
   can be called while the world is stopped without the risk of a deadlock.
1173
   Because of this we MUST setup callbacks BEFORE we ever stop the world.
1174
   This should be called BEFORE any thread in created and WITHOUT the
1175
   allocation lock held. */
1176
 
1177
void GC_init_dyld() {
1178
  static GC_bool initialized = FALSE;
1179
  char *bind_fully_env = NULL;
1180
 
1181
  if(initialized) return;
1182
 
1183
#   ifdef DARWIN_DEBUG
1184
  GC_printf0("Registering dyld callbacks...\n");
1185
#   endif
1186
 
1187
  /* Apple's Documentation:
1188
     When you call _dyld_register_func_for_add_image, the dynamic linker runtime
1189
     calls the specified callback (func) once for each of the images that is
1190
     currently loaded into the program. When a new image is added to the program,
1191
     your callback is called again with the mach_header for the new image, and the
1192
     virtual memory slide amount of the new image.
1193
 
1194
     This WILL properly register already linked libraries and libraries
1195
     linked in the future
1196
  */
1197
 
1198
    _dyld_register_func_for_add_image(GC_dyld_image_add);
1199
    _dyld_register_func_for_remove_image(GC_dyld_image_remove);
1200
 
1201
    /* Set this early to avoid reentrancy issues. */
1202
    initialized = TRUE;
1203
 
1204
    bind_fully_env = getenv("DYLD_BIND_AT_LAUNCH");
1205
 
1206
    if (bind_fully_env == NULL) {
1207
#   ifdef DARWIN_DEBUG
1208
      GC_printf0("Forcing full bind of GC code...\n");
1209
#   endif
1210
 
1211
      if(!_dyld_bind_fully_image_containing_address((unsigned long*)GC_malloc))
1212
        GC_abort("_dyld_bind_fully_image_containing_address failed");
1213
    }
1214
 
1215
}
1216
 
1217
#define HAVE_REGISTER_MAIN_STATIC_DATA
1218
GC_bool GC_register_main_static_data()
1219
{
1220
  /* Already done through dyld callbacks */
1221
  return FALSE;
1222
}
1223
 
1224
#endif /* DARWIN */
1225
 
1226
#else /* !DYNAMIC_LOADING */
1227
 
1228
#ifdef PCR
1229
 
1230
#   include "il/PCR_IL.h"
1231
#   include "th/PCR_ThCtl.h"
1232
#   include "mm/PCR_MM.h"
1233
 
1234
void GC_register_dynamic_libraries()
1235
{
1236
    /* Add new static data areas of dynamically loaded modules. */
1237
        {
1238
          PCR_IL_LoadedFile * p = PCR_IL_GetLastLoadedFile();
1239
          PCR_IL_LoadedSegment * q;
1240
 
1241
          /* Skip uncommited files */
1242
          while (p != NIL && !(p -> lf_commitPoint)) {
1243
              /* The loading of this file has not yet been committed    */
1244
              /* Hence its description could be inconsistent.           */
1245
              /* Furthermore, it hasn't yet been run.  Hence its data   */
1246
              /* segments can't possibly reference heap allocated       */
1247
              /* objects.                                               */
1248
              p = p -> lf_prev;
1249
          }
1250
          for (; p != NIL; p = p -> lf_prev) {
1251
            for (q = p -> lf_ls; q != NIL; q = q -> ls_next) {
1252
              if ((q -> ls_flags & PCR_IL_SegFlags_Traced_MASK)
1253
                  == PCR_IL_SegFlags_Traced_on) {
1254
                GC_add_roots_inner
1255
                        ((char *)(q -> ls_addr),
1256
                         (char *)(q -> ls_addr) + q -> ls_bytes,
1257
                         TRUE);
1258
              }
1259
            }
1260
          }
1261
        }
1262
}
1263
 
1264
 
1265
#else /* !PCR */
1266
 
1267
void GC_register_dynamic_libraries(){}
1268
 
1269
int GC_no_dynamic_loading;
1270
 
1271
#endif /* !PCR */
1272
 
1273
#endif /* !DYNAMIC_LOADING */
1274
 
1275
#ifndef HAVE_REGISTER_MAIN_STATIC_DATA
1276
 
1277
/* Do we need to separately register the main static data segment? */
1278
GC_bool GC_register_main_static_data()
1279
{
1280
  return TRUE;
1281
}
1282
#endif /* HAVE_REGISTER_MAIN_STATIC_DATA */
1283
 

powered by: WebSVN 2.1.0

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