📄 dyn_load.c
字号:
size_t regioninfosize = sizeof(regioninfo); size_t regionreturnsize; /* Obtain id of this process */ mypid = ldr_my_process(); /* For each module */ while (TRUE) { /* Get the next (first) module */ status = ldr_next_module(mypid, &moduleid); /* Any more modules? */ if (moduleid == LDR_NULL_MODULE) break; /* No more modules */ /* Check status AFTER checking moduleid because */ /* of a bug in the non-shared ldr_next_module stub */ if (status != 0 ) { GC_printf("dynamic_load: status = %d\n", status); { extern char *sys_errlist[]; extern int sys_nerr; extern int errno; if (errno <= sys_nerr) { GC_printf("dynamic_load: %s\n", sys_errlist[errno]); } else { GC_printf("dynamic_load: %d\n", errno); } } ABORT("ldr_next_module failed"); } /* Get the module information */ status = ldr_inq_module(mypid, moduleid, &moduleinfo, moduleinfosize, &modulereturnsize); if (status != 0 ) ABORT("ldr_inq_module failed"); /* is module for the main program (i.e. nonshared portion)? */ if (moduleinfo.lmi_flags & LDR_MAIN) continue; /* skip the main module */# ifdef DL_VERBOSE GC_printf("---Module---\n"); GC_printf("Module ID = %16ld\n", moduleinfo.lmi_modid); GC_printf("Count of regions = %16d\n", moduleinfo.lmi_nregion); GC_printf("flags for module = %16lx\n", moduleinfo.lmi_flags); GC_printf("pathname of module = \"%s\"\n", moduleinfo.lmi_name);# endif /* For each region in this module */ for (region = 0; region < moduleinfo.lmi_nregion; region++) { /* Get the region information */ status = ldr_inq_region(mypid, moduleid, region, ®ioninfo, regioninfosize, ®ionreturnsize); if (status != 0 ) ABORT("ldr_inq_region failed"); /* only process writable (data) regions */ if (! (regioninfo.lri_prot & LDR_W)) continue;# ifdef DL_VERBOSE GC_printf("--- Region ---\n"); GC_printf("Region number = %16ld\n", regioninfo.lri_region_no); GC_printf("Protection flags = %016x\n", regioninfo.lri_prot); GC_printf("Virtual address = %16p\n", regioninfo.lri_vaddr); GC_printf("Mapped address = %16p\n", regioninfo.lri_mapaddr); GC_printf("Region size = %16ld\n", regioninfo.lri_size); GC_printf("Region name = \"%s\"\n", regioninfo.lri_name);# endif /* register region as a garbage collection root */ GC_add_roots_inner ( (char *)regioninfo.lri_mapaddr, (char *)regioninfo.lri_mapaddr + regioninfo.lri_size, TRUE); } }}#endif#if defined(HPUX)#include <errno.h>#include <dl.h>extern char *sys_errlist[];extern int sys_nerr;void GC_register_dynamic_libraries(){ int status; int index = 1; /* Ordinal position in shared library search list */ struct shl_descriptor *shl_desc; /* Shared library info, see dl.h */ /* For each dynamic library loaded */ while (TRUE) { /* Get info about next shared library */ status = shl_get(index, &shl_desc); /* Check if this is the end of the list or if some error occured */ if (status != 0) {# ifdef GC_HPUX_THREADS /* I've seen errno values of 0. The man page is not clear */ /* as to whether errno should get set on a -1 return. */ break;# else if (errno == EINVAL) { break; /* Moved past end of shared library list --> finished */ } else { if (errno <= sys_nerr) { GC_printf("dynamic_load: %s\n", sys_errlist[errno]); } else { GC_printf("dynamic_load: %d\n", errno); } ABORT("shl_get failed"); }# endif }# ifdef DL_VERBOSE GC_printf("---Shared library---\n"); GC_printf("\tfilename = \"%s\"\n", shl_desc->filename); GC_printf("\tindex = %d\n", index); GC_printf("\thandle = %08x\n", (unsigned long) shl_desc->handle); GC_printf("\ttext seg. start = %08x\n", shl_desc->tstart); GC_printf("\ttext seg. end = %08x\n", shl_desc->tend); GC_printf("\tdata seg. start = %08x\n", shl_desc->dstart); GC_printf("\tdata seg. end = %08x\n", shl_desc->dend); GC_printf("\tref. count = %lu\n", shl_desc->ref_count);# endif /* register shared library's data segment as a garbage collection root */ GC_add_roots_inner((char *) shl_desc->dstart, (char *) shl_desc->dend, TRUE); index++; }}#endif /* HPUX */#ifdef AIX#pragma alloca#include <sys/ldr.h>#include <sys/errno.h>void GC_register_dynamic_libraries(){ int len; char *ldibuf; int ldibuflen; struct ld_info *ldi; ldibuf = alloca(ldibuflen = 8192); while ( (len = loadquery(L_GETINFO,ldibuf,ldibuflen)) < 0) { if (errno != ENOMEM) { ABORT("loadquery failed"); } ldibuf = alloca(ldibuflen *= 2); } ldi = (struct ld_info *)ldibuf; while (ldi) { len = ldi->ldinfo_next; GC_add_roots_inner( ldi->ldinfo_dataorg, (ptr_t)(unsigned long)ldi->ldinfo_dataorg + ldi->ldinfo_datasize, TRUE); ldi = len ? (struct ld_info *)((char *)ldi + len) : 0; }}#endif /* AIX */#ifdef DARWIN/* __private_extern__ hack required for pre-3.4 gcc versions. */#ifndef __private_extern__# define __private_extern__ extern# include <mach-o/dyld.h># undef __private_extern__#else# include <mach-o/dyld.h>#endif#include <mach-o/getsect.h>/*#define DARWIN_DEBUG*/const static struct { const char *seg; const char *sect;} GC_dyld_sections[] = { { SEG_DATA, SECT_DATA }, { SEG_DATA, SECT_BSS }, { SEG_DATA, SECT_COMMON }}; #ifdef DARWIN_DEBUGstatic const char *GC_dyld_name_for_hdr(const struct GC_MACH_HEADER *hdr) { unsigned long i,c; c = _dyld_image_count(); for(i=0;i<c;i++) if(_dyld_get_image_header(i) == hdr) return _dyld_get_image_name(i); return NULL;}#endif /* This should never be called by a thread holding the lock */static void GC_dyld_image_add(const struct GC_MACH_HEADER *hdr, intptr_t slide){ unsigned long start,end,i; const struct GC_MACH_SECTION *sec; if (GC_no_dls) return; for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {# if defined (__LP64__) sec = getsectbynamefromheader_64(# else sec = getsectbynamefromheader(# endif hdr, GC_dyld_sections[i].seg, GC_dyld_sections[i].sect); if(sec == NULL || sec->size == 0) continue; start = slide + sec->addr; end = start + sec->size;# ifdef DARWIN_DEBUG GC_printf("Adding section at %p-%p (%lu bytes) from image %s\n", start,end,sec->size,GC_dyld_name_for_hdr(hdr));# endif GC_add_roots((char*)start,(char*)end); }# ifdef DARWIN_DEBUG GC_print_static_roots();# endif}/* This should never be called by a thread holding the lock */static void GC_dyld_image_remove(const struct GC_MACH_HEADER *hdr, intptr_t slide){ unsigned long start,end,i; const struct GC_MACH_SECTION *sec; for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {# if defined (__LP64__) sec = getsectbynamefromheader_64(# else sec = getsectbynamefromheader(# endif hdr, GC_dyld_sections[i].seg, GC_dyld_sections[i].sect); if(sec == NULL || sec->size == 0) continue; start = slide + sec->addr; end = start + sec->size;# ifdef DARWIN_DEBUG GC_printf("Removing section at %p-%p (%lu bytes) from image %s\n", start,end,sec->size,GC_dyld_name_for_hdr(hdr));# endif GC_remove_roots((char*)start,(char*)end); }# ifdef DARWIN_DEBUG GC_print_static_roots();# endif}void GC_register_dynamic_libraries() { /* Currently does nothing. The callbacks are setup by GC_init_dyld() The dyld library takes it from there. */}/* The _dyld_* functions have an internal lock so no _dyld functions can be called while the world is stopped without the risk of a deadlock. Because of this we MUST setup callbacks BEFORE we ever stop the world. This should be called BEFORE any thread in created and WITHOUT the allocation lock held. */ void GC_init_dyld() { static GC_bool initialized = FALSE; char *bind_fully_env = NULL; if(initialized) return; # ifdef DARWIN_DEBUG GC_printf("Registering dyld callbacks...\n");# endif /* Apple's Documentation: When you call _dyld_register_func_for_add_image, the dynamic linker runtime calls the specified callback (func) once for each of the images that is currently loaded into the program. When a new image is added to the program, your callback is called again with the mach_header for the new image, and the virtual memory slide amount of the new image. This WILL properly register already linked libraries and libraries linked in the future */ _dyld_register_func_for_add_image(GC_dyld_image_add); _dyld_register_func_for_remove_image(GC_dyld_image_remove); /* Set this early to avoid reentrancy issues. */ initialized = TRUE; bind_fully_env = getenv("DYLD_BIND_AT_LAUNCH"); if (bind_fully_env == NULL) {# ifdef DARWIN_DEBUG GC_printf("Forcing full bind of GC code...\n");# endif if(!_dyld_bind_fully_image_containing_address((unsigned long*)GC_malloc)) GC_abort("_dyld_bind_fully_image_containing_address failed"); }}#define HAVE_REGISTER_MAIN_STATIC_DATAGC_bool GC_register_main_static_data(){ /* Already done through dyld callbacks */ return FALSE;}#endif /* DARWIN */#else /* !DYNAMIC_LOADING */#ifdef PCR# include "il/PCR_IL.h"# include "th/PCR_ThCtl.h"# include "mm/PCR_MM.h"void GC_register_dynamic_libraries(){ /* Add new static data areas of dynamically loaded modules. */ { PCR_IL_LoadedFile * p = PCR_IL_GetLastLoadedFile(); PCR_IL_LoadedSegment * q; /* Skip uncommited files */ while (p != NIL && !(p -> lf_commitPoint)) { /* The loading of this file has not yet been committed */ /* Hence its description could be inconsistent. */ /* Furthermore, it hasn't yet been run. Hence its data */ /* segments can't possibly reference heap allocated */ /* objects. */ p = p -> lf_prev; } for (; p != NIL; p = p -> lf_prev) { for (q = p -> lf_ls; q != NIL; q = q -> ls_next) { if ((q -> ls_flags & PCR_IL_SegFlags_Traced_MASK) == PCR_IL_SegFlags_Traced_on) { GC_add_roots_inner ((char *)(q -> ls_addr), (char *)(q -> ls_addr) + q -> ls_bytes, TRUE); } } } }}#else /* !PCR */void GC_register_dynamic_libraries(){}int GC_no_dynamic_loading;#endif /* !PCR */#endif /* !DYNAMIC_LOADING */#ifndef HAVE_REGISTER_MAIN_STATIC_DATA/* Do we need to separately register the main static data segment? */GC_bool GC_register_main_static_data(){ return TRUE;}/* Register a routine to filter dynamic library registration. */voidGC_register_has_static_roots_callback (int (*callback)(const char *, void *, size_t)) { GC_has_static_roots = callback;}#endif /* HAVE_REGISTER_MAIN_STATIC_DATA */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -