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

📄 dyn_load.c

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 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(_GNU_SOURCE)    /* Can't test LINUX, since this must be define 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#if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE)) \    && !defined(PCR)#if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && \    !defined(MSWIN32) && !defined(MSWINCE) && \    !(defined(ALPHA) && defined(OSF1)) && \    !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \    !defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \    !(defined(FREEBSD) && defined(__ELF__)) && \    !(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \    !defined(DARWIN) --> 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 SUNOS5DL#   include <sys/elf.h>#   include <dlfcn.h>#   include <link.h>#endif#ifdef SUNOS4#   include <dlfcn.h>#   include <link.h>#   include <a.out.h>  /* struct link_map field overrides */#   define l_next	lm_next#   define l_addr	lm_addr#   define l_name	lm_name#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#    else#      ifdef 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#  endif#if defined(SUNOS5DL) && !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 /* SUNOS5DL ... *//* 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(SUNOS4) && !defined(USE_PROC_FOR_LIBRARIES)#ifdef LINT    struct link_dynamic _DYNAMIC;#endifstatic struct link_map *GC_FirstDLOpenedLinkMap(){    extern struct link_dynamic _DYNAMIC;    if( &_DYNAMIC == 0) {        return(0);    }    return(_DYNAMIC.ld_un.ld_1->ld_loaded);}/* Return the address of the ld.so allocated common symbol	*//* with the least address, or 0 if none.			*/static ptr_t GC_first_common(){    ptr_t result = 0;    extern struct link_dynamic _DYNAMIC;    struct rtc_symb * curr_symbol;        if( &_DYNAMIC == 0) {        return(0);    }    curr_symbol = _DYNAMIC.ldd -> ldd_cp;    for (; curr_symbol != 0; curr_symbol = curr_symbol -> rtc_next) {        if (result == 0            || (ptr_t)(curr_symbol -> rtc_sp -> n_value) < result) {            result = (ptr_t)(curr_symbol -> rtc_sp -> n_value);        }    }    return(result);}#endif  /* SUNOS4 ... */# if defined(SUNOS4) || defined(SUNOS5DL)/* Add dynamic library data sections to the root set.		*/# if !defined(PCR) && !defined(GC_SOLARIS_THREADS) && defined(THREADS)#   ifndef SRC_M3	--> fix mutual exclusion with dlopen#   endif  /* We assume M3 programs don't call dlopen for now */# 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)    {#     ifdef SUNOS4	struct exec *e;	         e = (struct exec *) lm->lm_addr;        GC_add_roots_inner(      		    ((char *) (N_DATOFF(*e) + lm->lm_addr)),		    ((char *) (N_BSSADDR(*e) + e->a_bss + lm->lm_addr)),		    TRUE);#     endif#     ifdef SUNOS5DL	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    }#   ifdef SUNOS4      {      	static ptr_t common_start = 0;      	ptr_t common_end;      	extern ptr_t GC_find_limit();      	      	if (common_start == 0) common_start = GC_first_common();      	if (common_start != 0) {      	    common_end = GC_find_limit(common_start, TRUE);      	    GC_add_roots_inner((char *)common_start, (char *)common_end, TRUE);      	}      }#   endif}# endif /* !USE_PROC ... */# endif /* SUNOS */#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, word *start, word *end,                         char *prot_buf, unsigned int *maj_dev);word GC_apply_to_maps(word (*fn)(char *));	/* From os_dep.c	*/word GC_register_map_entries(char *maps){    char prot_buf[5];    char *buf_ptr = maps;    int count;    word start, end;    unsigned int maj_dev;    word least_ha, greatest_ha;    unsigned i;    word datastart = (word)(DATASTART);    /* Compute heap bounds. FIXME: Should be done by add_to_heap?	*/	least_ha = (word)(-1);	greatest_ha = 0;	for (i = 0; i < GC_n_heap_sects; ++i) {	    word sect_start = (word)GC_heap_sects[i].hs_start;	    word 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 < (word)GC_scratch_last_end_ptr)	    greatest_ha = (word)GC_scratch_last_end_ptr;     for (;;) {        buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev);	if (buf_ptr == NULL) return 1;	if (prot_buf[1] == 'w') {	    /* This is a writable mapping.  Add it to		*/	    /* the root set unless it is already otherwise	*/	    /* accounted for.					*/	    if (start <= (word)GC_stackbottom && end >= (word)GC_stackbottom) {		/* Stack mapping; discard	*/		continue;	    }#	    ifdef THREADS	      if (GC_segment_is_thread_stack(start, end)) continue;#	    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_apply_to_maps(GC_register_map_entries))       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) /* 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;	  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);

⌨️ 快捷键说明

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