dlfcn.c File Reference

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <limits.h>
#include <mach-o/dyld.h>
#include <mach-o/nlist.h>
#include <mach-o/getsect.h>
#include <asterisk/dlfcn-compat.h>

Include dependency graph for dlfcn.c:

Go to the source code of this file.

Data Structures

struct  dlthread
struct  dlstatus

Defines

#define __BSD_VISIBLE   1
#define dl_restrict   __restrict
#define LC_LOAD_WEAK_DYLIB   (0x18 | LC_REQ_DYLD)
#define LC_REQ_DYLD   0x80000000
#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED   0x4
#define NSADDIMAGE_OPTION_RETURN_ON_ERROR   0x1
#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND   0x0
#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR   0x4
#define ERR_STR_LEN   251
#define MAX_SEARCH_PATHS   32
#define MAGIC_DYLIB_OFI   ((NSObjectFileImage) 'DYOF')
#define MAGIC_DYLIB_MOD   ((NSModule) 'DYMO')
#define DL_IN_LIST   0x01
#define RTLD_SELF   ((void *) -3)

Functions

void * dlopen (const char *path, int mode)
void * dlsym (void *dl_restrict handle, const char *dl_restrict symbol)
int dlclose (void *handle)
const char * dlerror (void)
int dladdr (const void *dl_restrict p, Dl_info *dl_restrict info)


Define Documentation

#define __BSD_VISIBLE   1

Definition at line 48 of file dlfcn.c.

#define DL_IN_LIST   0x01

Definition at line 101 of file dlfcn.c.

#define dl_restrict   __restrict

Definition at line 53 of file dlfcn.c.

#define ERR_STR_LEN   251

Definition at line 91 of file dlfcn.c.

#define LC_LOAD_WEAK_DYLIB   (0x18 | LC_REQ_DYLD)

Definition at line 57 of file dlfcn.c.

#define LC_REQ_DYLD   0x80000000

Definition at line 64 of file dlfcn.c.

#define MAGIC_DYLIB_MOD   ((NSModule) 'DYMO')

Definition at line 98 of file dlfcn.c.

#define MAGIC_DYLIB_OFI   ((NSObjectFileImage) 'DYOF')

Definition at line 97 of file dlfcn.c.

#define MAX_SEARCH_PATHS   32

Definition at line 94 of file dlfcn.c.

#define NSADDIMAGE_OPTION_RETURN_ON_ERROR   0x1

Definition at line 70 of file dlfcn.c.

#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED   0x4

Definition at line 67 of file dlfcn.c.

#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND   0x0

Definition at line 73 of file dlfcn.c.

#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR   0x4

Definition at line 76 of file dlfcn.c.

#define RTLD_SELF   ((void *) -3)


Function Documentation

int dladdr ( const void *dl_restrict  p,
Dl_info *dl_restrict  info 
)

Definition at line 1166 of file dlfcn.c.

01167 {
01168 /*
01169    FIXME: USe the routine image_for_address.
01170 */
01171    unsigned long i;
01172    unsigned long j;
01173    unsigned long count = _dyld_image_count();
01174    struct mach_header *mh = 0;
01175    struct load_command *lc = 0;
01176    unsigned long addr = NULL;
01177    unsigned long table_off = (unsigned long)0;
01178    int found = 0;
01179    if (!info)
01180       return 0;
01181    dolock();
01182    resetdlerror();
01183    info->dli_fname = 0;
01184    info->dli_fbase = 0;
01185    info->dli_sname = 0;
01186    info->dli_saddr = 0;
01187 /* Some of this was swiped from code posted by Douglas Davidson <ddavidso AT apple DOT com>
01188  * to darwin-development AT lists DOT apple DOT com and slightly modified
01189  */
01190    for (i = 0; i < count; i++)
01191    {
01192       addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(i);
01193       mh = _dyld_get_image_header(i);
01194       if (mh)
01195       {
01196          lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
01197          for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
01198          {
01199             if (LC_SEGMENT == lc->cmd &&
01200                addr >= ((struct segment_command *)lc)->vmaddr &&
01201                addr <
01202                ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize)
01203             {
01204                info->dli_fname = _dyld_get_image_name(i);
01205                info->dli_fbase = (void *)mh;
01206                found = 1;
01207                break;
01208             }
01209          }
01210          if (found)
01211             break;
01212       }
01213    }
01214    if (!found)
01215    {
01216       dounlock();
01217       return 0;
01218    }
01219    lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
01220    for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
01221    {
01222       if (LC_SEGMENT == lc->cmd)
01223       {
01224          if (!strcmp(((struct segment_command *)lc)->segname, "__LINKEDIT"))
01225             break;
01226       }
01227    }
01228    table_off =
01229       ((unsigned long)((struct segment_command *)lc)->vmaddr) -
01230       ((unsigned long)((struct segment_command *)lc)->fileoff) + _dyld_get_image_vmaddr_slide(i);
01231    debug("table off %x", table_off);
01232 
01233    lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
01234    for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
01235    {
01236       if (LC_SYMTAB == lc->cmd)
01237       {
01238 
01239          struct nlist *symtable = (struct nlist *)(((struct symtab_command *)lc)->symoff + table_off);
01240          unsigned long numsyms = ((struct symtab_command *)lc)->nsyms;
01241          struct nlist *nearest = NULL;
01242          unsigned long diff = 0xffffffff;
01243          unsigned long strtable = (unsigned long)(((struct symtab_command *)lc)->stroff + table_off);
01244          debug("symtable %x", symtable);
01245          for (i = 0; i < numsyms; i++)
01246          {
01247             /* Ignore the following kinds of Symbols */
01248             if ((!symtable->n_value)   /* Undefined */
01249                || (symtable->n_type >= N_PEXT)  /* Debug symbol */
01250                || (!(symtable->n_type & N_EXT)) /* Local Symbol */
01251                )
01252             {
01253                symtable++;
01254                continue;
01255             }
01256             if ((addr >= symtable->n_value) && (diff >= (symtable->n_value - addr)))
01257             {
01258                diff = (unsigned long)symtable->n_value - addr;
01259                nearest = symtable;
01260             }
01261             symtable++;
01262          }
01263          if (nearest)
01264          {
01265             info->dli_saddr = nearest->n_value + ((void *)p - addr);
01266             info->dli_sname = (char *)(strtable + nearest->n_un.n_strx);
01267          }
01268       }
01269    }
01270    dounlock();
01271    return 1;
01272 }

int dlclose ( void *  handle  ) 

Definition at line 1040 of file dlfcn.c.

01041 {
01042    struct dlstatus *dls = handle;
01043    dolock();
01044    resetdlerror();
01045    if (!isValidStatus(dls))
01046    {
01047       goto dlcloseerror;
01048    }
01049    if (dls->module == MAGIC_DYLIB_MOD)
01050    {
01051       const char *name;
01052       if (!dls->lib)
01053       {
01054          name = "global context";
01055       }
01056       else
01057       {
01058          name = get_lib_name(dls->lib);
01059       }
01060       warning("trying to close a .dylib!");
01061       error("Not closing \"%s\" - dynamic libraries cannot be closed", name);
01062       goto dlcloseerror;
01063    }
01064    if (!dls->module)
01065    {
01066       error("module already closed");
01067       goto dlcloseerror;
01068    }
01069    
01070    if (dls->refs == 1)
01071    {
01072       unsigned long options = 0;
01073       void (*fini) (void);
01074       if ((fini = dlsymIntern(dls, "__fini", 0)))
01075       {
01076          debug("calling _fini()");
01077          fini();
01078       }
01079 #ifdef __ppc__
01080       options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
01081 #endif
01082 #if 1
01083 /*  Currently, if a module contains c++ static destructors and it is unloaded, we
01084  *  get a segfault in atexit(), due to compiler and dynamic loader differences of
01085  *  opinion, this works around that.
01086  *  I really need a way to figure out from code if this is still necessary.
01087  */
01088       if ((const struct section *)NULL !=
01089          getsectbynamefromheader(get_mach_header_from_NSModule(dls->module),
01090                            "__DATA", "__mod_term_func"))
01091       {
01092          options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
01093       }
01094 #endif
01095 #ifdef RTLD_NODELETE
01096       if (isFlagSet(dls->mode, RTLD_NODELETE))
01097          options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
01098 #endif
01099       if (!NSUnLinkModule(dls->module, options))
01100       {
01101          error("unable to unlink module");
01102          goto dlcloseerror;
01103       }
01104       dls->refs--;
01105       dls->module = 0;
01106       /* Note: the dlstatus struct dls is neither removed from the list
01107        * nor is the memory it occupies freed. This shouldn't pose a 
01108        * problem in mostly all cases, though.
01109        */
01110    }
01111    dounlock();
01112    return 0;
01113   dlcloseerror:
01114    dounlock();
01115    return 1;
01116 }

const char* dlerror ( void   ) 

Definition at line 1118 of file dlfcn.c.

01119 {
01120    struct dlthread  *tss;
01121    char * err_str;
01122    tss = pthread_getspecific(dlerror_key);
01123    err_str = tss->errstr;
01124    tss = pthread_getspecific(dlerror_key);
01125    if (tss->errset == 0)
01126       return 0;
01127    tss->errset = 0;  
01128    return (err_str );
01129 }

void* dlopen ( const char *  path,
int  mode 
)

Definition at line 896 of file dlfcn.c.

00897 {
00898    const struct stat *sbuf;
00899    struct dlstatus *dls;
00900    const char *fullPath;
00901    dlcompat_init_func();      /* Just in case */
00902    dolock();
00903    resetdlerror();
00904    if (!path)
00905    {
00906       dls = &mainStatus;
00907       goto dlopenok;
00908    }
00909    if (!(sbuf = findFile(path, &fullPath)))
00910    {
00911       error("file \"%s\" not found", path);
00912       goto dlopenerror;
00913    }
00914    /* Now checks that it hasn't been closed already */
00915    if ((dls = lookupStatus(sbuf)) && (dls->refs > 0))
00916    {
00917       /* debug("status found"); */
00918       dls = reference(dls, mode);
00919       goto dlopenok;
00920    }
00921 #ifdef   RTLD_NOLOAD
00922    if (isFlagSet(mode, RTLD_NOLOAD))
00923    {
00924       error("no existing handle and RTLD_NOLOAD specified");
00925       goto dlopenerror;
00926    }
00927 #endif
00928    if (isFlagSet(mode, RTLD_LAZY) && isFlagSet(mode, RTLD_NOW))
00929    {
00930       error("how can I load something both RTLD_LAZY and RTLD_NOW?");
00931       goto dlopenerror;
00932    }
00933    dls = loadModule(fullPath, sbuf, mode);
00934    
00935   dlopenok:
00936    dounlock();
00937    return (void *)dls;
00938   dlopenerror:
00939    dounlock();
00940    return NULL;
00941 }

void* dlsym ( void *dl_restrict  handle,
const char *dl_restrict  symbol 
)

Definition at line 944 of file dlfcn.c.

00945 {
00946    int sym_len = strlen(symbol);
00947    void *value = NULL;
00948    char *malloc_sym = NULL;
00949    dolock();
00950    malloc_sym = malloc(sym_len + 2);
00951    if (malloc_sym)
00952    {
00953       sprintf(malloc_sym, "_%s", symbol);
00954       value = dlsymIntern(handle, malloc_sym, 1);
00955       free(malloc_sym);
00956    }
00957    else
00958    {
00959       error("Unable to allocate memory");
00960       goto dlsymerror;
00961    }
00962    dounlock();
00963    return value;
00964   dlsymerror:
00965    dounlock();
00966    return NULL;
00967 }


Generated on Wed Oct 28 17:00:53 2009 for Asterisk by  doxygen 1.5.6