~ubuntu-branches/ubuntu/quantal/libgc/quantal

« back to all changes in this revision

Viewing changes to dyn_load.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger
  • Date: 2011-02-19 12:19:56 UTC
  • mfrom: (1.3.2 upstream) (0.1.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 14.
  • Revision ID: james.westby@ubuntu.com-20110219121956-67rb69xlt5nud3v2
Tags: 1:7.1-5
Upload to unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
 * None of this is safe with dlclose and incremental collection.
27
27
 * But then not much of anything is safe in the presence of dlclose.
28
28
 */
29
 
#if (defined(__linux__) || defined(__GLIBC__)) && !defined(_GNU_SOURCE)
30
 
    /* Can't test LINUX, since this must be define before other includes */
 
29
#if (defined(__linux__) || defined(__GLIBC__) || defined(__GNU__)) \
 
30
     && !defined(_GNU_SOURCE)
 
31
    /* Can't test LINUX, since this must be defined before other includes */
31
32
#   define _GNU_SOURCE
32
33
#endif
33
34
#if !defined(MACOS) && !defined(_WIN32_WCE)
49
50
#   undef GC_must_restore_redefined_dlopen
50
51
# endif
51
52
 
 
53
/* A user-supplied routine that is called to determine if a DSO must
 
54
   be scanned by the gc.  */
 
55
static int (*GC_has_static_roots)(const char *, void *, size_t);
 
56
 
 
57
 
52
58
#if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE)) \
53
59
    && !defined(PCR)
54
 
#if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && \
 
60
#if !defined(SOLARISDL) && !defined(IRIX5) && \
55
61
    !defined(MSWIN32) && !defined(MSWINCE) && \
56
62
    !(defined(ALPHA) && defined(OSF1)) && \
57
63
    !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \
58
 
    !defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \
 
64
    !defined(AIX) && !defined(SCO_ELF) && !defined(DGUX) && \
59
65
    !(defined(FREEBSD) && defined(__ELF__)) && \
60
66
    !(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \
61
 
    !defined(DARWIN)
 
67
    !defined(DARWIN) && !defined(CYGWIN32)
62
68
 --> We only know how to find data segments of dynamic libraries for the
63
69
 --> above.  Additional SVR4 variants might not be too
64
70
 --> hard to add.
65
71
#endif
66
72
 
67
73
#include <stdio.h>
68
 
#ifdef SUNOS5DL
 
74
#ifdef SOLARISDL
69
75
#   include <sys/elf.h>
70
76
#   include <dlfcn.h>
71
77
#   include <link.h>
72
78
#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
79
 
83
80
#if defined(NETBSD)
84
81
#   include <machine/elf_machdep.h>
102
99
#      else
103
100
#        define ElfW(type) Elf64_##type
104
101
#      endif
 
102
#    elif defined(NETBSD)
 
103
#      if ELFSIZE == 32
 
104
#        define ElfW(type) Elf32_##type
 
105
#      else
 
106
#        define ElfW(type) Elf64_##type
 
107
#      endif
105
108
#    else
106
 
#      ifdef NETBSD
107
 
#        if ELFSIZE == 32
108
 
#          define ElfW(type) Elf32_##type
109
 
#        else
110
 
#          define ElfW(type) Elf64_##type
111
 
#        endif
 
109
#      if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
 
110
#        define ElfW(type) Elf32_##type
112
111
#      else
113
 
#        if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
114
 
#          define ElfW(type) Elf32_##type
115
 
#        else
116
 
#          define ElfW(type) Elf64_##type
117
 
#        endif
 
112
#        define ElfW(type) Elf64_##type
118
113
#      endif
119
114
#    endif
120
115
#  endif
121
116
 
122
 
#if defined(SUNOS5DL) && !defined(USE_PROC_FOR_LIBRARIES)
 
117
#if defined(SOLARISDL) && !defined(USE_PROC_FOR_LIBRARIES)
123
118
 
124
119
#ifdef LINT
125
120
    Elf32_Dyn _DYNAMIC;
165
160
    return cachedResult;
166
161
}
167
162
 
168
 
#endif /* SUNOS5DL ... */
 
163
#endif /* SOLARISDL ... */
169
164
 
170
165
/* BTL: added to fix circular dlopen definition if GC_SOLARIS_THREADS defined */
171
166
# if defined(GC_must_restore_redefined_dlopen)
172
167
#   define dlopen GC_dlopen
173
168
# endif
174
169
 
175
 
#if defined(SUNOS4) && !defined(USE_PROC_FOR_LIBRARIES)
176
 
 
177
 
#ifdef LINT
178
 
    struct link_dynamic _DYNAMIC;
179
 
#endif
180
 
 
181
 
static struct link_map *
182
 
GC_FirstDLOpenedLinkMap()
183
 
{
184
 
    extern struct link_dynamic _DYNAMIC;
185
 
 
186
 
    if( &_DYNAMIC == 0) {
187
 
        return(0);
188
 
    }
189
 
    return(_DYNAMIC.ld_un.ld_1->ld_loaded);
190
 
}
191
 
 
192
 
/* Return the address of the ld.so allocated common symbol      */
193
 
/* with the least address, or 0 if none.                        */
194
 
static ptr_t GC_first_common()
195
 
{
196
 
    ptr_t result = 0;
197
 
    extern struct link_dynamic _DYNAMIC;
198
 
    struct rtc_symb * curr_symbol;
199
 
    
200
 
    if( &_DYNAMIC == 0) {
201
 
        return(0);
202
 
    }
203
 
    curr_symbol = _DYNAMIC.ldd -> ldd_cp;
204
 
    for (; curr_symbol != 0; curr_symbol = curr_symbol -> rtc_next) {
205
 
        if (result == 0
206
 
            || (ptr_t)(curr_symbol -> rtc_sp -> n_value) < result) {
207
 
            result = (ptr_t)(curr_symbol -> rtc_sp -> n_value);
208
 
        }
209
 
    }
210
 
    return(result);
211
 
}
212
 
 
213
 
#endif  /* SUNOS4 ... */
214
 
 
215
 
# if defined(SUNOS4) || defined(SUNOS5DL)
 
170
# if defined(SOLARISDL)
216
171
/* Add dynamic library data sections to the root set.           */
217
172
# if !defined(PCR) && !defined(GC_SOLARIS_THREADS) && defined(THREADS)
218
 
#   ifndef SRC_M3
219
173
        --> fix mutual exclusion with dlopen
220
 
#   endif  /* We assume M3 programs don't call dlopen for now */
221
174
# endif
222
175
 
223
176
# ifndef USE_PROC_FOR_LIBRARIES
229
182
  for (lm = GC_FirstDLOpenedLinkMap();
230
183
       lm != (struct link_map *) 0;  lm = lm->l_next)
231
184
    {
232
 
#     ifdef SUNOS4
233
 
        struct exec *e;
234
 
         
235
 
        e = (struct exec *) lm->lm_addr;
236
 
        GC_add_roots_inner(
237
 
                    ((char *) (N_DATOFF(*e) + lm->lm_addr)),
238
 
                    ((char *) (N_BSSADDR(*e) + e->a_bss + lm->lm_addr)),
239
 
                    TRUE);
240
 
#     endif
241
 
#     ifdef SUNOS5DL
242
185
        ElfW(Ehdr) * e;
243
186
        ElfW(Phdr) * p;
244
187
        unsigned long offset;
265
208
              break;
266
209
          }
267
210
        }
268
 
#     endif
269
211
    }
270
 
#   ifdef SUNOS4
271
 
      {
272
 
        static ptr_t common_start = 0;
273
 
        ptr_t common_end;
274
 
        extern ptr_t GC_find_limit();
275
 
        
276
 
        if (common_start == 0) common_start = GC_first_common();
277
 
        if (common_start != 0) {
278
 
            common_end = GC_find_limit(common_start, TRUE);
279
 
            GC_add_roots_inner((char *)common_start, (char *)common_end, TRUE);
280
 
        }
281
 
      }
282
 
#   endif
283
212
}
284
213
 
285
214
# endif /* !USE_PROC ... */
286
 
# endif /* SUNOS */
 
215
# endif /* SOLARISDL */
287
216
 
288
217
#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
289
218
    (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
304
233
        /* Repeatedly read until buffer is filled, or EOF is encountered */
305
234
        /* Defined in os_dep.c.                                          */
306
235
 
307
 
char *GC_parse_map_entry(char *buf_ptr, word *start, word *end,
308
 
                         char *prot_buf, unsigned int *maj_dev);
309
 
word GC_apply_to_maps(word (*fn)(char *));
 
236
char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end,
 
237
                         char **prot, unsigned int *maj_dev,
 
238
                         char **mapping_name);
 
239
char *GC_get_maps(void);
310
240
        /* From os_dep.c        */
311
241
 
 
242
/* Sort an array of HeapSects by start address.                         */
 
243
/* Unfortunately at least some versions of                              */
 
244
/* Linux qsort end up calling malloc by way of sysconf, and hence can't */
 
245
/* be used in the colector.  Hence we roll our own.  Should be          */
 
246
/* reasonably fast if the array is already mostly sorted, as we expect  */
 
247
/* it to be.                                                            */
 
248
void sort_heap_sects(struct HeapSect *base, size_t number_of_elements)
 
249
{
 
250
    signed_word n = (signed_word)number_of_elements;
 
251
    signed_word nsorted = 1;
 
252
    signed_word i;
 
253
 
 
254
    while (nsorted < n) {
 
255
      while (nsorted < n &&
 
256
             base[nsorted-1].hs_start < base[nsorted].hs_start)
 
257
          ++nsorted;
 
258
      if (nsorted == n) break;
 
259
      GC_ASSERT(base[nsorted-1].hs_start > base[nsorted].hs_start);
 
260
      i = nsorted - 1;
 
261
      while (i >= 0 && base[i].hs_start > base[i+1].hs_start) {
 
262
        struct HeapSect tmp = base[i];
 
263
        base[i] = base[i+1];
 
264
        base[i+1] = tmp;
 
265
        --i;
 
266
      }
 
267
      GC_ASSERT(base[nsorted-1].hs_start < base[nsorted].hs_start);
 
268
      ++nsorted;
 
269
    }
 
270
}
 
271
 
312
272
word GC_register_map_entries(char *maps)
313
273
{
314
 
    char prot_buf[5];
 
274
    char *prot;
315
275
    char *buf_ptr = maps;
316
276
    int count;
317
 
    word start, end;
 
277
    ptr_t start, end;
318
278
    unsigned int maj_dev;
319
 
    word least_ha, greatest_ha;
 
279
    ptr_t least_ha, greatest_ha;
320
280
    unsigned i;
321
 
    word datastart = (word)(DATASTART);
 
281
    ptr_t datastart = (ptr_t)(DATASTART);
322
282
 
323
 
    /* Compute heap bounds. FIXME: Should be done by add_to_heap?       */
324
 
        least_ha = (word)(-1);
325
 
        greatest_ha = 0;
326
 
        for (i = 0; i < GC_n_heap_sects; ++i) {
327
 
            word sect_start = (word)GC_heap_sects[i].hs_start;
328
 
            word sect_end = sect_start + GC_heap_sects[i].hs_bytes;
329
 
            if (sect_start < least_ha) least_ha = sect_start;
330
 
            if (sect_end > greatest_ha) greatest_ha = sect_end;
331
 
        }
332
 
        if (greatest_ha < (word)GC_scratch_last_end_ptr)
333
 
            greatest_ha = (word)GC_scratch_last_end_ptr; 
 
283
    GC_ASSERT(I_HOLD_LOCK());
 
284
    sort_heap_sects(GC_our_memory, GC_n_memory);
 
285
    least_ha = GC_our_memory[0].hs_start;
 
286
    greatest_ha = GC_our_memory[GC_n_memory-1].hs_start
 
287
                  + GC_our_memory[GC_n_memory-1].hs_bytes;
334
288
 
335
289
    for (;;) {
336
 
        buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev);
 
290
        buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, &prot, &maj_dev, 0);
337
291
        if (buf_ptr == NULL) return 1;
338
 
        if (prot_buf[1] == 'w') {
 
292
        if (prot[1] == 'w') {
339
293
            /* This is a writable mapping.  Add it to           */
340
294
            /* the root set unless it is already otherwise      */
341
295
            /* accounted for.                                   */
342
 
            if (start <= (word)GC_stackbottom && end >= (word)GC_stackbottom) {
 
296
            if (start <= GC_stackbottom && end >= GC_stackbottom) {
343
297
                /* Stack mapping; discard       */
344
298
                continue;
345
299
            }
346
300
#           ifdef THREADS
 
301
              /* This may fail, since a thread may already be           */
 
302
              /* unregistered, but its thread stack may still be there. */
 
303
              /* That can fail because the stack may disappear while    */
 
304
              /* we're marking.  Thus the marker is, and has to be      */
 
305
              /* prepared to recover from segmentation faults.          */
 
306
 
347
307
              if (GC_segment_is_thread_stack(start, end)) continue;
 
308
 
 
309
              /* FIXME: NPTL squirrels                                  */
 
310
              /* away pointers in pieces of the stack segment that we   */
 
311
              /* don't scan.  We work around this                       */
 
312
              /* by treating anything allocated by libpthread as        */
 
313
              /* uncollectable, as we do in some other cases.           */
 
314
              /* A specifically identified problem is that              */ 
 
315
              /* thread stacks contain pointers to dynamic thread       */
 
316
              /* vectors, which may be reused due to thread caching.    */
 
317
              /* They may not be marked if the thread is still live.    */
 
318
              /* This specific instance should be addressed by          */
 
319
              /* INCLUDE_LINUX_THREAD_DESCR, but that doesn't quite     */
 
320
              /* seem to suffice.                                       */
 
321
              /* We currently trace entire thread stacks, if they are   */
 
322
              /* are currently cached but unused.  This is              */
 
323
              /* very suboptimal for performance reasons.               */
348
324
#           endif
349
325
            /* We no longer exclude the main data segment.              */
350
 
            if (start < least_ha && end > least_ha) {
351
 
                end = least_ha;
352
 
            }
353
 
            if (start < greatest_ha && end > greatest_ha) {
354
 
                start = greatest_ha;
355
 
            }
356
 
            if (start >= least_ha && end <= greatest_ha) continue;
357
 
            GC_add_roots_inner((char *)start, (char *)end, TRUE);
 
326
            if (end <= least_ha || start >= greatest_ha) {
 
327
              /* The easy case; just trace entire segment */
 
328
              GC_add_roots_inner((char *)start, (char *)end, TRUE);
 
329
              continue;
 
330
            }
 
331
            /* Add sections that dont belong to us. */
 
332
              i = 0;
 
333
              while (GC_our_memory[i].hs_start + GC_our_memory[i].hs_bytes
 
334
                     < start)
 
335
                  ++i;
 
336
              GC_ASSERT(i < GC_n_memory);
 
337
              if (GC_our_memory[i].hs_start <= start) {
 
338
                  start = GC_our_memory[i].hs_start
 
339
                          + GC_our_memory[i].hs_bytes;
 
340
                  ++i;
 
341
              }
 
342
              while (i < GC_n_memory && GC_our_memory[i].hs_start < end
 
343
                     && start < end) {
 
344
                  if ((char *)start < GC_our_memory[i].hs_start)
 
345
                    GC_add_roots_inner((char *)start,
 
346
                                       GC_our_memory[i].hs_start, TRUE);
 
347
                  start = GC_our_memory[i].hs_start
 
348
                          + GC_our_memory[i].hs_bytes;
 
349
                  ++i;
 
350
              }
 
351
              if (start < end)
 
352
                  GC_add_roots_inner((char *)start, (char *)end, TRUE);
358
353
        }
359
354
    }
360
355
    return 1;
362
357
 
363
358
void GC_register_dynamic_libraries()
364
359
{
365
 
   if (!GC_apply_to_maps(GC_register_map_entries))
366
 
       ABORT("Failed to read /proc for library registration.");
 
360
    if (!GC_register_map_entries(GC_get_maps()))
 
361
        ABORT("Failed to read /proc for library registration.");
367
362
}
368
363
 
369
364
/* We now take care of the main data segment ourselves: */
370
365
GC_bool GC_register_main_static_data()
371
366
{
372
 
  return FALSE;
 
367
    return FALSE;
373
368
}
374
369
  
375
370
# define HAVE_REGISTER_MAIN_STATIC_DATA
411
406
        {
412
407
          if( !(p->p_flags & PF_W) ) break;
413
408
          start = ((char *)(p->p_vaddr)) + info->dlpi_addr;
 
409
 
 
410
          if (GC_has_static_roots
 
411
              && !GC_has_static_roots(info->dlpi_name, start, p->p_memsz))
 
412
            break;
 
413
 
414
414
          GC_add_roots_inner(start, start + p->p_memsz, TRUE);
415
415
        }
416
416
      break;
501
501
    if( cachedResult == 0 ) {
502
502
        int tag;
503
503
        for( dp = _DYNAMIC; (tag = dp->d_tag) != 0; dp++ ) {
504
 
            /* FIXME: The DT_DEBUG header is not mandated by the        */
505
 
            /* ELF spec.  This code appears to be dependent on          */
506
 
            /* idiosynchracies of older GNU tool chains.  If this code  */
507
 
            /* fails for you, the real problem is probably that it is   */
508
 
            /* being used at all.  You should be getting the            */
509
 
            /* dl_iterate_phdr version.                                 */
510
504
            if( tag == DT_DEBUG ) {
511
505
                struct link_map *lm
512
506
                        = ((struct r_debug *)(dp->d_un.d_ptr))->r_map;
589
583
    static prmap_t * addr_map = 0;
590
584
    static int current_sz = 0;  /* Number of records currently in addr_map */
591
585
    static int needed_sz;       /* Required size of addr_map            */
592
 
    register int i;
593
 
    register long flags;
594
 
    register ptr_t start;
595
 
    register ptr_t limit;
 
586
    int i;
 
587
    long flags;
 
588
    ptr_t start;
 
589
    ptr_t limit;
596
590
    ptr_t heap_start = (ptr_t)HEAP_START;
597
591
    ptr_t heap_end = heap_start;
598
592
 
599
 
#   ifdef SUNOS5DL
 
593
#   ifdef SOLARISDL
600
594
#     define MA_PHYS 0
601
 
#   endif /* SUNOS5DL */
 
595
#   endif /* SOLARISDL */
602
596
 
603
597
    if (fd < 0) {
604
598
      sprintf(buf, "/proc/%d", getpid());
610
604
      }
611
605
    }
612
606
    if (ioctl(fd, PIOCNMAP, &needed_sz) < 0) {
613
 
        GC_err_printf2("fd = %d, errno = %d\n", fd, errno);
 
607
        GC_err_printf("fd = %d, errno = %d\n", fd, errno);
614
608
        ABORT("/proc PIOCNMAP ioctl failed");
615
609
    }
616
610
    if (needed_sz >= current_sz) {
620
614
                                                (current_sz * sizeof(prmap_t)));
621
615
    }
622
616
    if (ioctl(fd, PIOCMAP, addr_map) < 0) {
623
 
        GC_err_printf4("fd = %d, errno = %d, needed_sz = %d, addr_map = 0x%X\n",
 
617
        GC_err_printf("fd = %d, errno = %d, needed_sz = %d, addr_map = 0x%X\n",
624
618
                        fd, errno, needed_sz, addr_map);
625
619
        ABORT("/proc PIOCMAP ioctl failed");
626
620
    };
631
625
    }
632
626
    for (i = 0; i < needed_sz; i++) {
633
627
        flags = addr_map[i].pr_mflags;
634
 
        if ((flags & (MA_BREAK | MA_STACK | MA_PHYS
 
628
        if ((flags & (MA_BREAK | MA_STACK | MA_PHYS
635
629
                      | MA_FETCHOP | MA_NOTCACHED)) != 0) goto irrelevant;
636
630
        if ((flags & (MA_READ | MA_WRITE)) != (MA_READ | MA_WRITE))
637
631
            goto irrelevant;
693
687
 
694
688
# endif /* USE_PROC || IRIX5 */
695
689
 
696
 
# if defined(MSWIN32) || defined(MSWINCE)
 
690
# if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
697
691
 
698
692
# define WIN32_LEAN_AND_MEAN
699
693
# define NOSERVICE
754
748
  
755
749
# define HAVE_REGISTER_MAIN_STATIC_DATA
756
750
 
757
 
  /* The frame buffer testing code is dead in this version.     */
758
 
  /* We leave it here temporarily in case the switch to just    */
759
 
  /* testing for MEM_IMAGE sections causes un expected          */
760
 
  /* problems.                                                  */
761
 
  GC_bool GC_warn_fb = TRUE;    /* Warn about traced likely     */
762
 
                                /* graphics memory.             */
763
 
  GC_bool GC_disallow_ignore_fb = FALSE;
764
 
  int GC_ignore_fb_mb;  /* Ignore mappings bigger than the      */
765
 
                        /* specified number of MB.              */
766
 
  GC_bool GC_ignore_fb = FALSE; /* Enable frame buffer  */
767
 
                                /* checking.            */
768
 
  
769
 
  /* Issue warning if tracing apparent framebuffer.             */
770
 
  /* This limits us to one warning, and it's a back door to     */
771
 
  /* disable that.                                              */
772
 
 
773
 
  /* Should [start, start+len) be treated as a frame buffer     */
774
 
  /* and ignored?                                               */
775
 
  /* Unfortunately, we currently are not quite sure how to tell */
776
 
  /* this automatically, and rely largely on user input.        */
777
 
  /* We expect that any mapping with type MEM_MAPPED (which     */
778
 
  /* apparently excludes library data sections) can be safely   */
779
 
  /* ignored.  But we're too completely remove this code in     */
780
 
  /* this version.                                              */
781
 
  /* Based on a very limited sample, it appears that:           */
782
 
  /*    - Frame buffer mappings appear as mappings of large     */
783
 
  /*      length, usually a bit less than a power of two.       */
784
 
  /*    - The definition of "a bit less" in the above cannot    */
785
 
  /*      be made more precise.                                 */
786
 
  /*    - Have a starting address at best 64K aligned.          */
787
 
  /*    - Have type == MEM_MAPPED.                              */
788
 
  static GC_bool is_frame_buffer(ptr_t start, size_t len, DWORD tp)
789
 
  {
790
 
    static GC_bool initialized = FALSE;
791
 
#   define MB (1024*1024)
792
 
#   define DEFAULT_FB_MB 15
793
 
#   define MIN_FB_MB 3
794
 
 
795
 
    if (GC_disallow_ignore_fb || tp != MEM_MAPPED) return FALSE;
796
 
    if (!initialized) {
797
 
      char * ignore_fb_string =  GETENV("GC_IGNORE_FB");
798
 
 
799
 
      if (0 != ignore_fb_string) {
800
 
        while (*ignore_fb_string == ' ' || *ignore_fb_string == '\t')
801
 
          ++ignore_fb_string;
802
 
        if (*ignore_fb_string == '\0') {
803
 
          GC_ignore_fb_mb = DEFAULT_FB_MB;
804
 
        } else {
805
 
          GC_ignore_fb_mb = atoi(ignore_fb_string);
806
 
          if (GC_ignore_fb_mb < MIN_FB_MB) {
807
 
            WARN("Bad GC_IGNORE_FB value.  Using %ld\n", DEFAULT_FB_MB);
808
 
            GC_ignore_fb_mb = DEFAULT_FB_MB;
809
 
          }
810
 
        }
811
 
        GC_ignore_fb = TRUE;
812
 
      } else {
813
 
        GC_ignore_fb_mb = DEFAULT_FB_MB;  /* For warning */
814
 
      }
815
 
      initialized = TRUE;
816
 
    }
817
 
    if (len >= ((size_t)GC_ignore_fb_mb << 20)) {
818
 
      if (GC_ignore_fb) {
819
 
        return TRUE;
820
 
      } else {
821
 
        if (GC_warn_fb) {
822
 
          WARN("Possible frame buffer mapping at 0x%lx: \n"
823
 
               "\tConsider setting GC_IGNORE_FB to improve performance.\n",
824
 
               start);
825
 
          GC_warn_fb = FALSE;
826
 
        }
827
 
        return FALSE;
828
 
      }
829
 
    } else {
830
 
      return FALSE;
831
 
    }
832
 
  }
833
 
 
834
751
# ifdef DEBUG_VIRTUALQUERY
835
752
  void GC_dump_meminfo(MEMORY_BASIC_INFORMATION *buf)
836
753
  {
837
 
    GC_printf4("BaseAddress = %lx, AllocationBase = %lx, RegionSize = %lx(%lu)\n",
 
754
    GC_printf("BaseAddress = %lx, AllocationBase = %lx, RegionSize = %lx(%lu)\n",
838
755
               buf -> BaseAddress, buf -> AllocationBase, buf -> RegionSize,
839
756
               buf -> RegionSize);
840
 
    GC_printf4("\tAllocationProtect = %lx, State = %lx, Protect = %lx, "
 
757
    GC_printf("\tAllocationProtect = %lx, State = %lx, Protect = %lx, "
841
758
               "Type = %lx\n",
842
759
               buf -> AllocationProtect, buf -> State, buf -> Protect,
843
760
               buf -> Type);
850
767
  void GC_register_dynamic_libraries()
851
768
  {
852
769
    MEMORY_BASIC_INFORMATION buf;
853
 
    DWORD result;
 
770
    size_t result;
854
771
    DWORD protect;
855
772
    LPVOID p;
856
773
    char * base;
861
778
#   endif
862
779
    base = limit = p = GC_sysinfo.lpMinimumApplicationAddress;
863
780
#   if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION)
864
 
    /* Only the first 32 MB of address space belongs to the current process */
865
 
    while (p < (LPVOID)0x02000000) {
 
781
      /* Only the first 32 MB of address space belongs to the current process */
 
782
      while (p < (LPVOID)0x02000000) {
866
783
        result = VirtualQuery(p, &buf, sizeof(buf));
867
784
        if (result == 0) {
868
785
            /* Page is free; advance to the next possible allocation base */
871
788
                 & ~(GC_sysinfo.dwAllocationGranularity-1));
872
789
        } else
873
790
#   else
874
 
    while (p < GC_sysinfo.lpMaximumApplicationAddress) {
 
791
      while (p < GC_sysinfo.lpMaximumApplicationAddress) {
875
792
        result = VirtualQuery(p, &buf, sizeof(buf));
876
793
#   endif
877
794
        {
884
801
                && (protect == PAGE_EXECUTE_READWRITE
885
802
                    || protect == PAGE_READWRITE)
886
803
                && !GC_is_heap_base(buf.AllocationBase)
887
 
                /* This used to check for
888
 
                 * !is_frame_buffer(p, buf.RegionSize, buf.Type)
889
 
                 * instead of just checking for MEM_IMAGE.
890
 
                 * If something breaks, change it back. */
891
 
                /* There is some evidence that we cannot always
892
 
                 * ignore MEM_PRIVATE sections under Windows ME
893
 
                 * and predecessors.  Hence we now also check for
894
 
                 * that case.   */
895
 
                && (buf.Type == MEM_IMAGE ||
896
 
                    !GC_wnt && buf.Type == MEM_PRIVATE)) {  
 
804
                /* There is some evidence that we cannot always
 
805
                 * ignore MEM_PRIVATE sections under Windows ME
 
806
                 * and predecessors.  Hence we now also check for
 
807
                 * that case.   */
 
808
                && (buf.Type == MEM_IMAGE ||
 
809
                    !GC_wnt && buf.Type == MEM_PRIVATE)) {
897
810
#               ifdef DEBUG_VIRTUALQUERY
898
811
                  GC_dump_meminfo(&buf);
899
812
#               endif
910
823
    GC_cond_add_roots(base, limit);
911
824
  }
912
825
 
913
 
#endif /* MSWIN32 || MSWINCE */
 
826
#endif /* MSWIN32 || MSWINCE || CYGWIN32 */
914
827
  
915
828
#if defined(ALPHA) && defined(OSF1)
916
829
 
949
862
      /* Check status AFTER checking moduleid because */
950
863
      /* of a bug in the non-shared ldr_next_module stub */
951
864
        if (status != 0 ) {
952
 
            GC_printf1("dynamic_load: status = %ld\n", (long)status);
 
865
            GC_printf("dynamic_load: status = %d\n", status);
953
866
            {
954
867
                extern char *sys_errlist[];
955
868
                extern int sys_nerr;
956
869
                extern int errno;
957
870
                if (errno <= sys_nerr) {
958
 
                    GC_printf1("dynamic_load: %s\n", (long)sys_errlist[errno]);
 
871
                    GC_printf("dynamic_load: %s\n", sys_errlist[errno]);
959
872
               } else {
960
 
                    GC_printf1("dynamic_load: %d\n", (long)errno);
 
873
                    GC_printf("dynamic_load: %d\n", errno);
961
874
                }
962
875
        }
963
876
            ABORT("ldr_next_module failed");
973
886
          if (moduleinfo.lmi_flags & LDR_MAIN)
974
887
              continue;    /* skip the main module */
975
888
 
976
 
#     ifdef VERBOSE
 
889
#     ifdef DL_VERBOSE
977
890
          GC_printf("---Module---\n");
978
891
          GC_printf("Module ID            = %16ld\n", moduleinfo.lmi_modid);
979
892
          GC_printf("Count of regions     = %16d\n", moduleinfo.lmi_nregion);
994
907
            if (! (regioninfo.lri_prot & LDR_W))
995
908
                continue;
996
909
 
997
 
#         ifdef VERBOSE
 
910
#         ifdef DL_VERBOSE
998
911
              GC_printf("--- Region ---\n");
999
912
              GC_printf("Region number    = %16ld\n",
1000
913
                        regioninfo.lri_region_no);
1021
934
#include <errno.h>
1022
935
#include <dl.h>
1023
936
 
1024
 
extern int errno;
1025
937
extern char *sys_errlist[];
1026
938
extern int sys_nerr;
1027
939
 
1048
960
              break; /* Moved past end of shared library list --> finished */
1049
961
          } else {
1050
962
              if (errno <= sys_nerr) {
1051
 
                    GC_printf1("dynamic_load: %s\n", (long) sys_errlist[errno]);
 
963
                    GC_printf("dynamic_load: %s\n", sys_errlist[errno]);
1052
964
              } else {
1053
 
                    GC_printf1("dynamic_load: %d\n", (long) errno);
 
965
                    GC_printf("dynamic_load: %d\n", errno);
1054
966
              }
1055
967
              ABORT("shl_get failed");
1056
968
          }
1057
969
#        endif
1058
970
        }
1059
971
 
1060
 
#     ifdef VERBOSE
1061
 
          GC_printf0("---Shared library---\n");
1062
 
          GC_printf1("\tfilename        = \"%s\"\n", shl_desc->filename);
1063
 
          GC_printf1("\tindex           = %d\n", index);
1064
 
          GC_printf1("\thandle          = %08x\n",
 
972
#     ifdef DL_VERBOSE
 
973
          GC_printf("---Shared library---\n");
 
974
          GC_printf("\tfilename        = \"%s\"\n", shl_desc->filename);
 
975
          GC_printf("\tindex           = %d\n", index);
 
976
          GC_printf("\thandle          = %08x\n",
1065
977
                                        (unsigned long) shl_desc->handle);
1066
 
          GC_printf1("\ttext seg. start = %08x\n", shl_desc->tstart);
1067
 
          GC_printf1("\ttext seg. end   = %08x\n", shl_desc->tend);
1068
 
          GC_printf1("\tdata seg. start = %08x\n", shl_desc->dstart);
1069
 
          GC_printf1("\tdata seg. end   = %08x\n", shl_desc->dend);
1070
 
          GC_printf1("\tref. count      = %lu\n", shl_desc->ref_count);
 
978
          GC_printf("\ttext seg. start = %08x\n", shl_desc->tstart);
 
979
          GC_printf("\ttext seg. end   = %08x\n", shl_desc->tend);
 
980
          GC_printf("\tdata seg. start = %08x\n", shl_desc->dstart);
 
981
          GC_printf("\tdata seg. end   = %08x\n", shl_desc->dend);
 
982
          GC_printf("\tref. count      = %lu\n", shl_desc->ref_count);
1071
983
#     endif
1072
984
 
1073
985
      /* register shared library's data segment as a garbage collection root */
1079
991
}
1080
992
#endif /* HPUX */
1081
993
 
1082
 
#ifdef RS6000
 
994
#ifdef AIX
1083
995
#pragma alloca
1084
996
#include <sys/ldr.h>
1085
997
#include <sys/errno.h>
1110
1022
                ldi = len ? (struct ld_info *)((char *)ldi + len) : 0;
1111
1023
        }
1112
1024
}
1113
 
#endif /* RS6000 */
 
1025
#endif /* AIX */
1114
1026
 
1115
1027
#ifdef DARWIN
1116
1028
 
1136
1048
};
1137
1049
    
1138
1050
#ifdef DARWIN_DEBUG
1139
 
static const char *GC_dyld_name_for_hdr(struct mach_header *hdr) {
 
1051
static const char *GC_dyld_name_for_hdr(const struct GC_MACH_HEADER *hdr) {
1140
1052
    unsigned long i,c;
1141
1053
    c = _dyld_image_count();
1142
1054
    for(i=0;i<c;i++) if(_dyld_get_image_header(i) == hdr)
1146
1058
#endif
1147
1059
        
1148
1060
/* This should never be called by a thread holding the lock */
1149
 
static void GC_dyld_image_add(struct mach_header* hdr, unsigned long slide) {
 
1061
static void GC_dyld_image_add(const struct GC_MACH_HEADER *hdr, intptr_t slide)
 
1062
{
1150
1063
    unsigned long start,end,i;
1151
 
    const struct section *sec;
 
1064
    const struct GC_MACH_SECTION *sec;
1152
1065
    if (GC_no_dls) return;
1153
1066
    for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
1154
 
        sec = getsectbynamefromheader(
1155
 
            hdr,GC_dyld_sections[i].seg,GC_dyld_sections[i].sect);
1156
 
        if(sec == NULL || sec->size == 0) continue;
1157
 
        start = slide + sec->addr;
1158
 
        end = start + sec->size;
1159
 
#       ifdef DARWIN_DEBUG
1160
 
            GC_printf4("Adding section at %p-%p (%lu bytes) from image %s\n",
1161
 
                start,end,sec->size,GC_dyld_name_for_hdr(hdr));
1162
 
#       endif
1163
 
        GC_add_roots((char*)start,(char*)end);
 
1067
      sec = GC_GETSECTBYNAME(hdr, GC_dyld_sections[i].seg,
 
1068
                             GC_dyld_sections[i].sect);
 
1069
      if(sec == NULL || sec->size == 0) continue;
 
1070
      start = slide + sec->addr;
 
1071
      end = start + sec->size;
 
1072
#   ifdef DARWIN_DEBUG
 
1073
      GC_printf("Adding section at %p-%p (%lu bytes) from image %s\n",
 
1074
                start,end,sec->size,GC_dyld_name_for_hdr(hdr));
 
1075
#   endif
 
1076
      GC_add_roots((char*)start,(char*)end);
1164
1077
    }
1165
1078
#   ifdef DARWIN_DEBUG
1166
 
        GC_print_static_roots();
 
1079
       GC_print_static_roots();
1167
1080
#   endif
1168
1081
}
1169
1082
 
1170
1083
/* This should never be called by a thread holding the lock */
1171
 
static void GC_dyld_image_remove(struct mach_header* hdr, unsigned long slide) {
 
1084
static void GC_dyld_image_remove(const struct GC_MACH_HEADER *hdr,
 
1085
                                 intptr_t slide)
 
1086
{
1172
1087
    unsigned long start,end,i;
1173
 
    const struct section *sec;
 
1088
    const struct GC_MACH_SECTION *sec;
1174
1089
    for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
1175
 
        sec = getsectbynamefromheader(
1176
 
            hdr,GC_dyld_sections[i].seg,GC_dyld_sections[i].sect);
1177
 
        if(sec == NULL || sec->size == 0) continue;
1178
 
        start = slide + sec->addr;
1179
 
        end = start + sec->size;
1180
 
#       ifdef DARWIN_DEBUG
1181
 
            GC_printf4("Removing section at %p-%p (%lu bytes) from image %s\n",
1182
 
                start,end,sec->size,GC_dyld_name_for_hdr(hdr));
1183
 
#               endif
1184
 
        GC_remove_roots((char*)start,(char*)end);
 
1090
      sec = GC_GETSECTBYNAME(hdr, GC_dyld_sections[i].seg,
 
1091
                             GC_dyld_sections[i].sect);
 
1092
      if(sec == NULL || sec->size == 0) continue;
 
1093
      start = slide + sec->addr;
 
1094
      end = start + sec->size;
 
1095
#   ifdef DARWIN_DEBUG
 
1096
      GC_printf("Removing section at %p-%p (%lu bytes) from image %s\n",
 
1097
                start,end,sec->size,GC_dyld_name_for_hdr(hdr));
 
1098
#   endif
 
1099
      GC_remove_roots((char*)start,(char*)end);
1185
1100
    }
1186
1101
#   ifdef DARWIN_DEBUG
1187
 
        GC_print_static_roots();
 
1102
        GC_print_static_roots();
1188
1103
#   endif
1189
1104
}
1190
1105
 
1206
1121
  if(initialized) return;
1207
1122
  
1208
1123
#   ifdef DARWIN_DEBUG
1209
 
  GC_printf0("Registering dyld callbacks...\n");
 
1124
      GC_printf("Registering dyld callbacks...\n");
1210
1125
#   endif
1211
1126
  
1212
1127
  /* Apple's Documentation:
1230
1145
    
1231
1146
    if (bind_fully_env == NULL) {
1232
1147
#   ifdef DARWIN_DEBUG
1233
 
      GC_printf0("Forcing full bind of GC code...\n");
 
1148
      GC_printf("Forcing full bind of GC code...\n");
1234
1149
#   endif
1235
1150
      
1236
1151
      if(!_dyld_bind_fully_image_containing_address((unsigned long*)GC_malloc))
1304
1219
{
1305
1220
  return TRUE;
1306
1221
}
 
1222
 
 
1223
/* Register a routine to filter dynamic library registration.  */
 
1224
void
 
1225
GC_register_has_static_roots_callback
 
1226
  (int (*callback)(const char *, void *, size_t)) {
 
1227
  GC_has_static_roots = callback;
 
1228
}
 
1229
 
1307
1230
#endif /* HAVE_REGISTER_MAIN_STATIC_DATA */
1308
1231