/* * Copyright (c) 1991-1993 by Xerox Corporation. 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 copy this garbage collector for any purpose, * provided the above notices are retained on all copies. * Author: Bill Janssen * Modified by: Hans Boehm */ /* * 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 ... */ #include "gc←private.h" #ifdef DYNAMIC←LOADING #if !(defined(M68K) && defined(SUNOS)) && !defined(SPARC) --> We only know how to find data segments of dynamic libraries under SunOS 4.X #endif #include <stdio.h> #if defined SUNOS5 # include <sys/elf.h> # include <dlfcn.h> # include <link.h> #else # 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 #ifdef SUNOS5 static struct link←map * GC←FirstDLOpenedLinkMap() { extern Elf32←Dyn ←DYNAMIC; Elf32←Dyn *dp; struct r←debug *r; static struct link←map * cachedResult = 0; if( &←DYNAMIC == 0) { return(0); } if( cachedResult == 0 ) { int tag; for( dp = ((Elf32←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 # ifdef SUNOS4 static struct link←map * GC←FirstDLOpenedLinkMap() { extern struct link←dynamic ←DYNAMIC; if( &←DYNAMIC == 0) { return(0); } return(←DYNAMIC.ld←un.ld←1->ld←loaded); } # endif /* Add dynamic library data sections to the root set. */ # if !defined(PCR) && defined(THREADS) --> fix mutual exclusion with dlopen # endif void 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))); # endif # ifdef SUNOS5 Elf32←Ehdr * e; Elf32←Phdr * p; unsigned long offset; char * start; register int i; e = (Elf32←Ehdr *) lm->l←addr; p = ((Elf32←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 ); } break; default: break; } } # endif } } #else void GC←register←dynamic←libraries(){} int GC←no←dynamic←loading; #endif