[BACK]Return to dyn_load.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc

Annotation of OpenXM_contrib2/asir2000/gc/dyn_load.c, Revision 1.7

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>