⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dyn_load.c

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved. * Copyright (c) 1997 by Silicon Graphics.  All rights reserved. * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK. * * Permission is hereby granted to use or copy this program * for any purpose,  provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. * * Original author: Bill Janssen * Heavily modified by Hans Boehm and others *//* * This is incredibly OS specific code for tracking down data sections in * dynamic libraries.  There appears to be no way of doing this quickly * without groveling through undocumented data structures.  We would argue * that this is a bug in the design of the dlopen interface.  THIS CODE * MAY BREAK IN FUTURE OS RELEASES.  If this matters to you, don't hesitate * to let your vendor know ... * * None of this is safe with dlclose and incremental collection. * But then not much of anything is safe in the presence of dlclose. */#if (defined(__linux__) || defined(__GLIBC__) || defined(__GNU__)) \     && !defined(_GNU_SOURCE)    /* Can't test LINUX, since this must be defined before other includes */#   define _GNU_SOURCE#endif#if !defined(MACOS) && !defined(_WIN32_WCE)#  include <sys/types.h>#endif#include "private/gc_priv.h"/* BTL: avoid circular redefinition of dlopen if GC_SOLARIS_THREADS defined */# if (defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS)) \      && defined(dlopen) && !defined(GC_USE_LD_WRAP)    /* To support threads in Solaris, gc.h interposes on dlopen by       */    /* defining "dlopen" to be "GC_dlopen", which is implemented below.  */    /* However, both GC_FirstDLOpenedLinkMap() and GC_dlopen() use the   */    /* real system dlopen() in their implementation. We first remove     */    /* gc.h's dlopen definition and restore it later, after GC_dlopen(). */#   undef dlopen#   define GC_must_restore_redefined_dlopen# else#   undef GC_must_restore_redefined_dlopen# endif/* A user-supplied routine that is called to determine if a DSO must   be scanned by the gc.  */static int (*GC_has_static_roots)(const char *, void *, size_t);#if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE)) \    && !defined(PCR)#if !defined(SOLARISDL) && !defined(IRIX5) && \    !defined(MSWIN32) && !defined(MSWINCE) && \    !(defined(ALPHA) && defined(OSF1)) && \    !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \    !defined(AIX) && !defined(SCO_ELF) && !defined(DGUX) && \    !(defined(FREEBSD) && defined(__ELF__)) && \    !(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \    !defined(DARWIN) && !defined(CYGWIN32) --> We only know how to find data segments of dynamic libraries for the --> above.  Additional SVR4 variants might not be too --> hard to add.#endif#include <stdio.h>#ifdef SOLARISDL#   include <sys/elf.h>#   include <dlfcn.h>#   include <link.h>#endif#if defined(NETBSD)#   include <machine/elf_machdep.h>#   define ELFSIZE ARCH_ELFSIZE#endif#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \    (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \    (defined(NETBSD) && defined(__ELF__)) || defined(HURD)#   include <stddef.h>#   include <elf.h>#   include <link.h>#endif/* Newer versions of GNU/Linux define this macro.  We * define it similarly for any ELF systems that don't.  */#  ifndef ElfW#    if defined(FREEBSD)#      if __ELF_WORD_SIZE == 32#        define ElfW(type) Elf32_##type#      else#        define ElfW(type) Elf64_##type#      endif#    elif defined(NETBSD)#      if ELFSIZE == 32#        define ElfW(type) Elf32_##type#      else#        define ElfW(type) Elf64_##type#      endif#    else#      if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32#        define ElfW(type) Elf32_##type#      else#        define ElfW(type) Elf64_##type#      endif#    endif#  endif#if defined(SOLARISDL) && !defined(USE_PROC_FOR_LIBRARIES)#ifdef LINT    Elf32_Dyn _DYNAMIC;#endifstatic struct link_map *GC_FirstDLOpenedLinkMap(){    extern ElfW(Dyn) _DYNAMIC;    ElfW(Dyn) *dp;    struct r_debug *r;    static struct link_map * cachedResult = 0;    static ElfW(Dyn) *dynStructureAddr = 0;    			/* BTL: added to avoid Solaris 5.3 ld.so _DYNAMIC bug */#   ifdef SUNOS53_SHARED_LIB	/* BTL: Avoid the Solaris 5.3 bug that _DYNAMIC isn't being set	*/	/* up properly in dynamically linked .so's. This means we have	*/	/* to use its value in the set of original object files loaded	*/	/* at program startup.						*/	if( dynStructureAddr == 0 ) {	  void* startupSyms = dlopen(0, RTLD_LAZY);	  dynStructureAddr = (ElfW(Dyn)*)dlsym(startupSyms, "_DYNAMIC");		}#   else	dynStructureAddr = &_DYNAMIC;#   endif    if( dynStructureAddr == 0) {        return(0);    }    if( cachedResult == 0 ) {        int tag;        for( dp = ((ElfW(Dyn) *)(&_DYNAMIC)); (tag = dp->d_tag) != 0; dp++ ) {            if( tag == DT_DEBUG ) {                struct link_map *lm                        = ((struct r_debug *)(dp->d_un.d_ptr))->r_map;                if( lm != 0 ) cachedResult = lm->l_next; /* might be NIL */                break;            }        }    }    return cachedResult;}#endif /* SOLARISDL ... *//* BTL: added to fix circular dlopen definition if GC_SOLARIS_THREADS defined */# if defined(GC_must_restore_redefined_dlopen)#   define dlopen GC_dlopen# endif# if defined(SOLARISDL)/* Add dynamic library data sections to the root set.		*/# if !defined(PCR) && !defined(GC_SOLARIS_THREADS) && defined(THREADS)	--> fix mutual exclusion with dlopen# endif# ifndef USE_PROC_FOR_LIBRARIESvoid GC_register_dynamic_libraries(){  struct link_map *lm = GC_FirstDLOpenedLinkMap();    for (lm = GC_FirstDLOpenedLinkMap();       lm != (struct link_map *) 0;  lm = lm->l_next)    {	ElfW(Ehdr) * e;        ElfW(Phdr) * p;        unsigned long offset;        char * start;        register int i;        	e = (ElfW(Ehdr) *) lm->l_addr;        p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff));        offset = ((unsigned long)(lm->l_addr));        for( i = 0; i < (int)(e->e_phnum); ((i++),(p++)) ) {          switch( p->p_type ) {            case PT_LOAD:              {                if( !(p->p_flags & PF_W) ) break;                start = ((char *)(p->p_vaddr)) + offset;                GC_add_roots_inner(                  start,                  start + p->p_memsz,                  TRUE                );              }              break;            default:              break;          }	}    }}# endif /* !USE_PROC ... */# endif /* SOLARISDL */#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \    (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \    (defined(NETBSD) && defined(__ELF__)) || defined(HURD)#ifdef USE_PROC_FOR_LIBRARIES#include <string.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#define MAPS_BUF_SIZE (32*1024)extern ssize_t GC_repeat_read(int fd, char *buf, size_t count);	/* Repeatedly read until buffer is filled, or EOF is encountered */	/* Defined in os_dep.c.  					 */char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end,                         char **prot, unsigned int *maj_dev,			 char **mapping_name);char *GC_get_maps(void);	/* From os_dep.c	*/word GC_register_map_entries(char *maps){    char *prot;    char *buf_ptr = maps;    int count;    ptr_t start, end;    unsigned int maj_dev;    ptr_t least_ha, greatest_ha;    unsigned i;    ptr_t datastart = (ptr_t)(DATASTART);    /* Compute heap bounds. FIXME: Should work if heap and roots are 	*/    /* interleaved?							*/	least_ha = (ptr_t)(word)(-1);	greatest_ha = 0;	for (i = 0; i < GC_n_heap_sects; ++i) {	    ptr_t sect_start = GC_heap_sects[i].hs_start;	    ptr_t sect_end = sect_start + GC_heap_sects[i].hs_bytes;	    if (sect_start < least_ha) least_ha = sect_start;	    if (sect_end > greatest_ha) greatest_ha = sect_end;        }    	if (greatest_ha < (ptr_t)GC_scratch_last_end_ptr)	    greatest_ha = (ptr_t)GC_scratch_last_end_ptr;     for (;;) {        buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, &prot, &maj_dev, 0);	if (buf_ptr == NULL) return 1;	if (prot[1] == 'w') {	    /* This is a writable mapping.  Add it to		*/	    /* the root set unless it is already otherwise	*/	    /* accounted for.					*/	    if (start <= GC_stackbottom && end >= GC_stackbottom) {		/* Stack mapping; discard	*/		continue;	    }#	    ifdef THREADS	      /* This may fail, since a thread may already be 		*/	      /* unregistered, but its thread stack may still be there.	*/	      /* That can fail because the stack may disappear while	*/	      /* we're marking.  Thus the marker is, and has to be	*/	      /* prepared to recover from segmentation faults.		*/	      if (GC_segment_is_thread_stack(start, end)) continue;	      /* FIXME: REDIRECT_MALLOC actually works with threads on	*/	      /* LINUX/IA64 if we omit this check.  The problem is that	*/	      /* thread stacks contain pointers to dynamic thread	*/	      /* vectors, which may be reused due to thread caching.	*/	      /* Currently they may not be marked if the thread is 	*/	      /* still live.						*/	      /* For dead threads, we trace the whole stack, which is	*/	      /* very suboptimal for performance reasons.		*/#	    endif	    /* We no longer exclude the main data segment.		*/	    if (start < least_ha && end > least_ha) {		end = least_ha;	    }	    if (start < greatest_ha && end > greatest_ha) {		start = greatest_ha;	    }	    if (start >= least_ha && end <= greatest_ha) continue;	    GC_add_roots_inner((char *)start, (char *)end, TRUE);	}    }    return 1;}void GC_register_dynamic_libraries(){    if (!GC_register_map_entries(GC_get_maps()))        ABORT("Failed to read /proc for library registration.");}/* We now take care of the main data segment ourselves: */GC_bool GC_register_main_static_data(){    return FALSE;}  # define HAVE_REGISTER_MAIN_STATIC_DATA#endif /* USE_PROC_FOR_LIBRARIES */#if !defined(USE_PROC_FOR_LIBRARIES)/* The following is the preferred way to walk dynamic libraries	*//* For glibc 2.2.4+.  Unfortunately, it doesn't work for older	*//* versions.  Thanks to Jakub Jelinek for most of the code.	*/# if (defined(LINUX) || defined (__GLIBC__)) /* Are others OK here, too? */ \     && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \         || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG))) /* We have the header files for a glibc that includes dl_iterate_phdr.	*//* It may still not be available in the library on the target system.   *//* Thus we also treat it as a weak symbol.				*/#define HAVE_DL_ITERATE_PHDRstatic int GC_register_dynlib_callback(info, size, ptr)     struct dl_phdr_info * info;     size_t size;     void * ptr;{  const ElfW(Phdr) * p;  char * start;  register int i;  /* Make sure struct dl_phdr_info is at least as big as we need.  */  if (size < offsetof (struct dl_phdr_info, dlpi_phnum)      + sizeof (info->dlpi_phnum))    return -1;  p = info->dlpi_phdr;  for( i = 0; i < (int)(info->dlpi_phnum); ((i++),(p++)) ) {    switch( p->p_type ) {      case PT_LOAD:	{	  if( !(p->p_flags & PF_W) ) break;	  start = ((char *)(p->p_vaddr)) + info->dlpi_addr;	  if (GC_has_static_roots	      && !GC_has_static_roots(info->dlpi_name, start, p->p_memsz))	    break;	  GC_add_roots_inner(start, start + p->p_memsz, TRUE);	}      break;      default:	break;    }  }  * (int *)ptr = 1;	/* Signal that we were called */  return 0;}     /* Return TRUE if we succeed, FALSE if dl_iterate_phdr wasn't there. */#pragma weak dl_iterate_phdrGC_bool GC_register_dynamic_libraries_dl_iterate_phdr(){  if (dl_iterate_phdr) {    int did_something = 0;    dl_iterate_phdr(GC_register_dynlib_callback, &did_something);    if (!did_something) {	/* dl_iterate_phdr may forget the static data segment in	*/	/* statically linked executables.				*/	GC_add_roots_inner(DATASTART, (char *)(DATAEND), TRUE);#       if defined(DATASTART2)          GC_add_roots_inner(DATASTART2, (char *)(DATAEND2), TRUE);#       endif    }    return TRUE;  } else {    return FALSE;  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -