/*
* 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