Fri Aug 24 02:25:11 2007

Asterisk developer's documentation


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  dlstatus
struct  dlthread

Defines

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

Functions

static struct dlstatusallocStatus (void)
static void debug (const char *fmt,...)
int dladdr (const void *dl_restrict p, Dl_info *dl_restrict info)
int dlclose (void *handle)
static void dlcompat_cleanup (void)
static void dlcompat_init_func (void)
const char * dlerror (void)
static void dlerrorfree (void *data)
void * dlopen (const char *path, int mode)
void * dlsym (void *dl_restrict handle, const char *dl_restrict symbol)
static void * dlsymIntern (struct dlstatus *dls, const char *symbol, int canSetError)
static void dolock (void)
static void dounlock (void)
static const char * dyld_error_str (void)
static void error (const char *str,...)
static struct stat * findFile (const char *file, const char **fullPath)
static const char * get_lib_name (const struct mach_header *mh)
static struct mach_header * get_mach_header_from_NSModule (NSModule *mod)
static const char * getFullPath (int i, const char *file)
static const char * getSearchPath (int i)
static struct mach_header * image_for_address (const void *address)
static void insertStatus (struct dlstatus *dls, const struct stat *sbuf)
static int isFlagSet (int mode, int flag)
static int isValidStatus (struct dlstatus *status)
static struct dlstatusloadModule (const char *path, const struct stat *sbuf, int mode)
static struct dlstatuslookupStatus (const struct stat *sbuf)
static struct mach_header * my_find_image (const char *name)
static int promoteLocalToGlobal (struct dlstatus *dls)
static void * reference (struct dlstatus *dls, int mode)
static void resetdlerror (void)
static const char * safegetenv (const char *s)
static NSSymbol * search_linked_libs (const struct mach_header *mh, const char *symbol)
static const char * searchList (void)
static void warning (const char *str)

Variables

static pthread_mutex_t dlcompat_mutex
static pthread_key_t dlerror_key
static struct mach_header *(*) dyld_NSAddImage (const char *, unsigned long)=0
static int(*) dyld_NSIsSymbolNameDefinedInImage (const struct mach_header *, const char *)=0
static NSSymbol(*) dyld_NSLookupSymbolInImage (const struct mach_header *, const char *, unsigned long)=0
static struct dlstatus mainStatus = { 0, MAGIC_DYLIB_MOD, NULL, -1, RTLD_GLOBAL, 0, 0, 0 }
static struct dlstatusstqueue = &mainStatus


Define Documentation

#define __BSD_VISIBLE   1

Definition at line 48 of file dlfcn.c.

#define DL_IN_LIST   0x01

Definition at line 102 of file dlfcn.c.

Referenced by insertStatus(), and loadModule().

#define dl_restrict   __restrict

Definition at line 54 of file dlfcn.c.

#define ERR_STR_LEN   251

Definition at line 92 of file dlfcn.c.

Referenced by error().

#define LC_LOAD_WEAK_DYLIB   (0x18 | LC_REQ_DYLD)

Definition at line 58 of file dlfcn.c.

Referenced by search_linked_libs().

#define LC_REQ_DYLD   0x80000000

Definition at line 65 of file dlfcn.c.

#define MAGIC_DYLIB_MOD   ((NSModule) 'DYMO')

Definition at line 99 of file dlfcn.c.

Referenced by dlclose(), dlsymIntern(), loadModule(), promoteLocalToGlobal(), and reference().

#define MAGIC_DYLIB_OFI   ((NSObjectFileImage) 'DYOF')

Definition at line 98 of file dlfcn.c.

Referenced by loadModule().

#define MAX_SEARCH_PATHS   32

Definition at line 95 of file dlfcn.c.

Referenced by getSearchPath().

#define NSADDIMAGE_OPTION_RETURN_ON_ERROR   0x1

Definition at line 71 of file dlfcn.c.

Referenced by loadModule(), and my_find_image().

#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED   0x4

Definition at line 68 of file dlfcn.c.

Referenced by my_find_image().

#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND   0x0

Definition at line 74 of file dlfcn.c.

Referenced by dlsymIntern(), and search_linked_libs().

#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR   0x4

Definition at line 77 of file dlfcn.c.

Referenced by dlsymIntern(), and search_linked_libs().

#define RTLD_SELF   ((void *) -3)

Referenced by dlsymIntern().


Function Documentation

static struct dlstatus * allocStatus ( void   )  [static]

Definition at line 428 of file dlfcn.c.

References malloc, dlstatus::module, dlstatus::next, and stqueue.

Referenced by loadModule().

00429 {
00430    struct dlstatus *dls;
00431 #ifdef REUSE_STATUS
00432    dls = stqueue;
00433    while (dls && dls->module)
00434       dls = dls->next;
00435    if (!dls)
00436 #endif
00437       dls = malloc(sizeof(*dls));
00438    dls->flags = 0;
00439    return dls;
00440 }

static void debug ( const char *  fmt,
  ... 
) [static]

Definition at line 183 of file dlfcn.c.

00184 {
00185 #if DEBUG > 1
00186    va_list arg;
00187    va_start(arg, fmt);
00188    fprintf(stderr, "DLDEBUG: ");
00189    vfprintf(stderr, fmt, arg);
00190    fprintf(stderr, "\n");
00191    fflush(stderr);
00192    va_end(arg);
00193 #endif
00194 }

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

Definition at line 1167 of file dlfcn.c.

References debug, dolock(), dounlock(), and resetdlerror().

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

int dlclose ( void *  handle  ) 

Definition at line 1041 of file dlfcn.c.

References debug, dlsymIntern(), dolock(), dounlock(), error(), get_lib_name(), get_mach_header_from_NSModule(), isFlagSet(), isValidStatus(), dlstatus::lib, MAGIC_DYLIB_MOD, dlstatus::mode, dlstatus::module, name, dlstatus::refs, resetdlerror(), RTLD_NODELETE, and warning().

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

static void dlcompat_cleanup ( void   )  [static]

Definition at line 824 of file dlfcn.c.

References dlcompat_mutex, dlerror_key, free, getSearchPath(), mainStatus, dlstatus::next, pthread_mutex_destroy, searchList(), and stqueue.

Referenced by dlcompat_init_func().

00825 {
00826    struct dlstatus *dls;
00827    struct dlstatus *next;
00828    char *data;
00829    data = (char *)searchList();
00830    if ( data )
00831       free( data );
00832    data =   (char *)getSearchPath(-1);
00833    if ( data )
00834       free( data );
00835    pthread_mutex_destroy(&dlcompat_mutex);
00836    pthread_key_delete(dlerror_key);
00837    next = stqueue;
00838    while (next && (next != &mainStatus))
00839    {
00840       dls = next;
00841       next = dls->next;
00842       free(dls);
00843    }
00844 }

static void dlcompat_init_func ( void   )  [static]

Definition at line 801 of file dlfcn.c.

References dlcompat_cleanup(), dlcompat_mutex, dlerror_key, dlerrorfree(), dyld_NSAddImage, dyld_NSIsSymbolNameDefinedInImage, dyld_NSLookupSymbolInImage, and pthread_mutex_init.

Referenced by dlopen().

00802 {
00803    static int inited = 0;
00804    if (!inited)
00805    {
00806       inited = 1;
00807       _dyld_func_lookup("__dyld_NSAddImage", (unsigned long *)&dyld_NSAddImage);
00808       _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",
00809                     (unsigned long *)&dyld_NSIsSymbolNameDefinedInImage);
00810       _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (unsigned long *)&dyld_NSLookupSymbolInImage);
00811       if (pthread_mutex_init(&dlcompat_mutex, NULL))
00812          exit(1);
00813       if (pthread_key_create(&dlerror_key, &dlerrorfree))
00814          exit(1);
00815       /* And be neat and tidy and clean up after ourselves */  
00816       atexit(dlcompat_cleanup);
00817    }
00818 }

const char* dlerror ( void   ) 

Definition at line 1119 of file dlfcn.c.

References dlerror_key, dlthread::errset, and dlthread::errstr.

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

static void dlerrorfree ( void *  data  )  [static]

Definition at line 853 of file dlfcn.c.

References free.

Referenced by dlcompat_init_func().

00854 {
00855    free(data);
00856 }

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

Definition at line 897 of file dlfcn.c.

References dlcompat_init_func(), dolock(), dounlock(), error(), findFile(), isFlagSet(), loadModule(), lookupStatus(), mainStatus, reference(), dlstatus::refs, resetdlerror(), RTLD_LAZY, RTLD_NOLOAD, and RTLD_NOW.

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

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

Definition at line 945 of file dlfcn.c.

References dlsymIntern(), dolock(), dounlock(), error(), free, and malloc.

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

static void * dlsymIntern ( struct dlstatus dls,
const char *  symbol,
int  canSetError 
) [static]

Definition at line 560 of file dlfcn.c.

References debug, dyld_error_str(), dyld_NSIsSymbolNameDefinedInImage, dyld_NSLookupSymbolInImage, error(), free, get_mach_header_from_NSModule(), image_for_address(), isValidStatus(), dlstatus::lib, MAGIC_DYLIB_MOD, mainStatus, malloc, dlstatus::module, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND, NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR, resetdlerror(), RTLD_DEFAULT, RTLD_NEXT, RTLD_SELF, and search_linked_libs().

Referenced by dlclose(), dlsym(), and loadModule().

00561 {
00562    NSSymbol *nssym = 0;
00563    void *caller = __builtin_return_address(1);  /* Be *very* careful about inlining */
00564    const struct mach_header *caller_mh = 0;
00565    const char* savedErrorStr = NULL;
00566    resetdlerror();
00567 #ifndef RTLD_SELF
00568 #define  RTLD_SELF      ((void *) -3)
00569 #endif
00570    if (NULL == dls)
00571       dls = RTLD_SELF;
00572    if ((RTLD_NEXT == dls) || (RTLD_SELF == dls))
00573    {
00574       if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
00575       {
00576          caller_mh = image_for_address(caller);
00577          if (RTLD_SELF == dls)
00578          {
00579             /* FIXME: We should be using the NSModule api, if SELF is an MH_BUNDLE
00580              * But it appears to work anyway, and looking at the code in dyld_libfuncs.c
00581              * this is acceptable.
00582              */
00583             if (dyld_NSIsSymbolNameDefinedInImage(caller_mh, symbol))
00584             {
00585                nssym = dyld_NSLookupSymbolInImage(caller_mh,
00586                                           symbol,
00587                                           NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
00588                                           NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
00589             }
00590          }
00591          if (!nssym)
00592          {
00593             if (RTLD_SELF == dls)
00594                savedErrorStr = dyld_error_str();
00595             nssym = search_linked_libs(caller_mh, symbol);
00596          }
00597       }
00598       else
00599       {
00600          if (canSetError)
00601             error("RTLD_SELF and RTLD_NEXT are not supported");
00602          return NULL;
00603       }
00604    }
00605    if (!nssym)
00606    {
00607 
00608       if (RTLD_DEFAULT == dls)
00609       {
00610          dls = &mainStatus;
00611       }
00612       if (!isValidStatus(dls))
00613          return NULL;
00614 
00615       if (dls->module != MAGIC_DYLIB_MOD)
00616       {
00617          nssym = NSLookupSymbolInModule(dls->module, symbol);
00618          if (!nssym && NSIsSymbolNameDefined(symbol))
00619          {
00620             debug("Searching dependencies");
00621             savedErrorStr = dyld_error_str();
00622             nssym = search_linked_libs(get_mach_header_from_NSModule(dls->module), symbol);
00623          }
00624       }
00625       else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
00626       {
00627          if (dyld_NSIsSymbolNameDefinedInImage(dls->lib, symbol))
00628          {
00629             nssym = dyld_NSLookupSymbolInImage(dls->lib,
00630                                        symbol,
00631                                        NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
00632                                        NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
00633          }
00634          else if (NSIsSymbolNameDefined(symbol))
00635          {
00636             debug("Searching dependencies");
00637             savedErrorStr = dyld_error_str();
00638             nssym = search_linked_libs(dls->lib, symbol);
00639          }
00640       }
00641       else if (dls->module == MAGIC_DYLIB_MOD)
00642       {
00643          /* Global context, use NSLookupAndBindSymbol */
00644          if (NSIsSymbolNameDefined(symbol))
00645          {
00646             /* There doesn't seem to be a return on error option for this call???
00647                this is potentially broken, if binding fails, it will improperly
00648                exit the application. */
00649             nssym = NSLookupAndBindSymbol(symbol);
00650          }
00651          else
00652          {
00653             if (savedErrorStr)
00654                free((char*)savedErrorStr);         
00655             savedErrorStr = malloc(256);
00656             snprintf((char*)savedErrorStr, 256, "Symbol \"%s\" not in global context",symbol);  
00657          }
00658       }
00659    }
00660    /* Error reporting */
00661    if (!nssym)
00662    {
00663       if (!savedErrorStr || !strlen(savedErrorStr))
00664       {
00665          if (savedErrorStr)
00666             free((char*)savedErrorStr);
00667          savedErrorStr = malloc(256);
00668          snprintf((char*)savedErrorStr, 256,"Symbol \"%s\" not found",symbol);
00669       }
00670       if (canSetError)
00671       {
00672          error(savedErrorStr);
00673       }
00674       else
00675       {
00676          debug(savedErrorStr);
00677       }
00678       if (savedErrorStr)
00679          free((char*)savedErrorStr);
00680       return NULL;
00681    }
00682    return NSAddressOfSymbol(nssym);
00683 }

static void dolock ( void   )  [inline, static]

Definition at line 862 of file dlfcn.c.

References dlcompat_mutex, dlerror_key, dlthread::errset, dlthread::lockcnt, malloc, and pthread_mutex_lock.

Referenced by dladdr(), dlclose(), dlopen(), and dlsym().

00863 {
00864    int err = 0;
00865    struct dlthread *tss;
00866    tss = pthread_getspecific(dlerror_key);
00867    if (!tss)
00868    {
00869       tss = malloc(sizeof(struct dlthread));
00870       tss->lockcnt = 0;
00871       tss->errset = 0;
00872       if (pthread_setspecific(dlerror_key, tss))
00873       {
00874          fprintf(stderr,"dlcompat: pthread_setspecific failed\n");
00875          exit(1);
00876       }
00877    }
00878    if (!tss->lockcnt)
00879       err = pthread_mutex_lock(&dlcompat_mutex);
00880    tss->lockcnt = tss->lockcnt +1;  
00881    if (err)
00882       exit(err);
00883 }

static void dounlock ( void   )  [inline, static]

Definition at line 885 of file dlfcn.c.

References dlcompat_mutex, dlerror_key, dlthread::lockcnt, and pthread_mutex_unlock.

Referenced by dladdr(), dlclose(), dlopen(), and dlsym().

00886 {
00887    int err = 0;
00888    struct dlthread *tss;
00889    tss = pthread_getspecific(dlerror_key);
00890    tss->lockcnt = tss->lockcnt -1;
00891    if (!tss->lockcnt)
00892       err = pthread_mutex_unlock(&dlcompat_mutex);
00893    if (err)
00894       exit(err);
00895 }

static const char * dyld_error_str ( void   )  [inline, static]

Definition at line 544 of file dlfcn.c.

References malloc.

Referenced by dlsymIntern().

00545 {
00546    NSLinkEditErrors dylder;
00547    int dylderno;
00548    const char *dylderrstr;
00549    const char *dyldfile;
00550    const char* retStr = NULL;
00551    NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderrstr);
00552    if (dylderrstr && strlen(dylderrstr))
00553    {
00554       retStr = malloc(strlen(dylderrstr) +1);
00555       strcpy((char*)retStr,dylderrstr);
00556    }
00557    return retStr;
00558 }

static void error ( const char *  str,
  ... 
) [static]

Definition at line 196 of file dlfcn.c.

References debug, dlerror_key, ERR_STR_LEN, dlthread::errset, and dlthread::errstr.

Referenced by __ast_pbx_run(), aji_register_query_handler(), append_string(), ast_unload_resource(), dlclose(), dlopen(), dlsym(), dlsymIntern(), gtalk_response(), handle_request(), handle_request_invite(), iax2_hangup(), iax2_write(), isValidStatus(), loadModule(), mgcp_devicestate(), mysql_log(), ogg_vorbis_open(), osp_check_destination(), osp_create_provider(), osp_create_transaction(), osp_finish(), osp_load(), osp_lookup(), osp_next(), osp_validate_token(), park_exec(), reference(), and send_packet().

00197 {
00198    va_list arg;
00199    struct dlthread  *tss;
00200    char * err_str;
00201    va_start(arg, str);
00202    tss = pthread_getspecific(dlerror_key);
00203    err_str = tss->errstr;
00204    strncpy(err_str, "dlcompat: ", ERR_STR_LEN);
00205    vsnprintf(err_str + 10, ERR_STR_LEN - 10, str, arg);
00206    va_end(arg);
00207    debug("ERROR: %s\n", err_str);
00208    tss->errset = 1;
00209 }

static struct stat * findFile ( const char *  file,
const char **  fullPath 
) [static]

Definition at line 359 of file dlfcn.c.

References debug, and getFullPath().

Referenced by dlopen().

00360 {
00361    int i = 0;
00362    static struct stat sbuf;
00363    char *fileName;
00364    debug("finding file %s", file);
00365    *fullPath = file;
00366    if (0 == stat(file, &sbuf))
00367       return &sbuf;
00368    if (strchr(file, '/'))
00369       return 0;            /* If the path had a / we don't look in env var places */
00370    fileName = NULL;
00371    if (!fileName)
00372       fileName = (char *)file;
00373    while ((*fullPath = getFullPath(i++, fileName)))
00374    {
00375       if (0 == stat(*fullPath, &sbuf))
00376          return &sbuf;
00377    }
00378    ;
00379    return 0;
00380 }

static const char * get_lib_name ( const struct mach_header *  mh  )  [static]

Definition at line 228 of file dlfcn.c.

Referenced by dlclose().

00229 {
00230    unsigned long count = _dyld_image_count();
00231    unsigned long i;
00232    const char *val = NULL;
00233    if (mh)
00234    {
00235       for (i = 0; i < count; i++)
00236       {
00237          if (mh == _dyld_get_image_header(i))
00238          {
00239             val = _dyld_get_image_name(i);
00240             break;
00241          }
00242       }
00243    }
00244    return val;
00245 }

static struct mach_header * get_mach_header_from_NSModule ( NSModule *  mod  )  [static]

Definition at line 251 of file dlfcn.c.

References debug.

Referenced by dlclose(), dlsymIntern(), and loadModule().

00252 {
00253    const char *mod_name = NSNameOfModule(mod);
00254    struct mach_header *mh = NULL;
00255    unsigned long count = _dyld_image_count();
00256    unsigned long i;
00257    debug("Module name: %s", mod_name);
00258    for (i = 0; i < count; i++)
00259    {
00260       if (!strcmp(mod_name, _dyld_get_image_name(i)))
00261       {
00262          mh = _dyld_get_image_header(i);
00263          break;
00264       }
00265    }
00266    return mh;
00267 }

static const char * getFullPath ( int  i,
const char *  file 
) [static]

Definition at line 344 of file dlfcn.c.

References getSearchPath().

Referenced by findFile().

00345 {
00346    static char buf[PATH_MAX];
00347    const char *path = getSearchPath(i);
00348    if (path)
00349    {
00350       snprintf(buf, PATH_MAX, "%s/%s", path, file);
00351    }
00352    return path ? buf : 0;
00353 }

static const char * getSearchPath ( int  i  )  [static]

Definition at line 298 of file dlfcn.c.

References calloc, debug, free, MAX_SEARCH_PATHS, searchList(), and strsep().

Referenced by dlcompat_cleanup(), and getFullPath().

00299 {
00300    static const char *list = 0;
00301    static char **path = (char **)0;
00302    static int end = 0;
00303    static int numsize = MAX_SEARCH_PATHS;
00304    static char **tmp;
00305    /* So we can call free() in the "destructor" we use i=-1 to return the alloc'd array */
00306    if (i == -1)
00307    {
00308       return (const char*)path;
00309    }
00310    if (!path)
00311    {
00312       path = (char **)calloc(MAX_SEARCH_PATHS, sizeof(char **));
00313    }
00314    if (!list && !end)
00315       list = searchList();
00316    if (i >= (numsize))
00317    {
00318       debug("Increasing size for long PATH");
00319       tmp = (char **)calloc((MAX_SEARCH_PATHS + numsize), sizeof(char **));
00320       if (tmp)
00321       {
00322          memcpy(tmp, path, sizeof(char **) * numsize);
00323          free(path);
00324          path = tmp;
00325          numsize += MAX_SEARCH_PATHS;
00326       }
00327       else
00328       {
00329          return 0;
00330       }
00331    }
00332 
00333    while (!path[i] && !end)
00334    {
00335       path[i] = strsep((char **)&list, ":");
00336 
00337       if (path[i][0] == 0)
00338          path[i] = 0;
00339       end = (list == 0);
00340    }
00341    return path[i];
00342 }

struct mach_header * image_for_address ( const void *  address  )  [static]

Definition at line 1135 of file dlfcn.c.

Referenced by dlsymIntern().

01136 {
01137    unsigned long i;
01138    unsigned long j;
01139    unsigned long count = _dyld_image_count();
01140    struct mach_header *mh = 0;
01141    struct load_command *lc = 0;
01142    unsigned long addr = NULL;
01143    for (i = 0; i < count; i++)
01144    {
01145       addr = (unsigned long)address - _dyld_get_image_vmaddr_slide(i);
01146       mh = _dyld_get_image_header(i);
01147       if (mh)
01148       {
01149          lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
01150          for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
01151          {
01152             if (LC_SEGMENT == lc->cmd &&
01153                addr >= ((struct segment_command *)lc)->vmaddr &&
01154                addr <
01155                ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize)
01156             {
01157                goto image_found;
01158             }
01159          }
01160       }
01161       mh = 0;
01162    }
01163   image_found:
01164    return mh;
01165 }

static void insertStatus ( struct dlstatus dls,
const struct stat *  sbuf 
) [static]

Definition at line 413 of file dlfcn.c.

References debug, dlstatus::device, DL_IN_LIST, dlstatus::flags, dlstatus::inode, dlstatus::mode, dlstatus::next, dlstatus::refs, and stqueue.

Referenced by loadModule().

00414 {
00415    debug("inserting status");
00416    dls->inode = sbuf->st_ino;
00417    dls->device = sbuf->st_dev;
00418    dls->refs = 0;
00419    dls->mode = 0;
00420    if ((dls->flags & DL_IN_LIST) == 0)
00421    {
00422       dls->next = stqueue;
00423       stqueue = dls;
00424       dls->flags |= DL_IN_LIST;
00425    }
00426 }

static int isFlagSet ( int  mode,
int  flag 
) [inline, static]

Definition at line 398 of file dlfcn.c.

Referenced by dlclose(), dlopen(), loadModule(), and reference().

00399 {
00400    return (mode & flag) == flag;
00401 }

static int isValidStatus ( struct dlstatus status  )  [static]

Definition at line 383 of file dlfcn.c.

References error(), FALSE, dlstatus::module, dlstatus::next, dlstatus::refs, stqueue, and TRUE.

Referenced by dlclose(), and dlsymIntern().

00384 {
00385    /* Walk the list to verify status is contained in it */
00386    struct dlstatus *dls = stqueue;
00387    while (dls && status != dls)
00388       dls = dls->next;
00389    if (dls == 0)
00390       error("invalid handle");
00391    else if ((dls->module == 0) || (dls->refs == 0))
00392       error("handle to closed library");
00393    else
00394       return TRUE;
00395    return FALSE;
00396 }

static struct dlstatus * loadModule ( const char *  path,
const struct stat *  sbuf,
int  mode 
) [static]

Definition at line 685 of file dlfcn.c.

References allocStatus(), debug, DL_IN_LIST, dlsymIntern(), dyld_NSAddImage, dyld_NSIsSymbolNameDefinedInImage, dyld_NSLookupSymbolInImage, error(), file, dlstatus::flags, free, get_mach_header_from_NSModule(), insertStatus(), isFlagSet(), dlstatus::lib, lookupStatus(), MAGIC_DYLIB_MOD, MAGIC_DYLIB_OFI, dlstatus::module, NSADDIMAGE_OPTION_RETURN_ON_ERROR, reference(), RTLD_GLOBAL, RTLD_NOW, and warning().

Referenced by dlopen().

00686 {
00687    NSObjectFileImage ofi = 0;
00688    NSObjectFileImageReturnCode ofirc;
00689    struct dlstatus *dls;
00690    NSLinkEditErrors ler;
00691    int lerno;
00692    const char *errstr;
00693    const char *file;
00694    void (*init) (void);
00695    ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
00696    switch (ofirc)
00697    {
00698       case NSObjectFileImageSuccess:
00699          break;
00700       case NSObjectFileImageInappropriateFile:
00701          if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
00702          {
00703             if (!isFlagSet(mode, RTLD_GLOBAL))
00704             {
00705                warning("trying to open a .dylib with RTLD_LOCAL");
00706                error("unable to open this file with RTLD_LOCAL");
00707                return NULL;
00708             }
00709          }
00710          else
00711          {
00712             error("opening this file is unsupported on this system");
00713             return NULL;
00714          }
00715          break;
00716       case NSObjectFileImageFailure:
00717          error("object file setup failure");
00718          return NULL;
00719       case NSObjectFileImageArch:
00720          error("no object for this architecture");
00721          return NULL;
00722       case NSObjectFileImageFormat:
00723          error("bad object file format");
00724          return NULL;
00725       case NSObjectFileImageAccess:
00726          error("can't read object file");
00727          return NULL;
00728       default:
00729          error("unknown error from NSCreateObjectFileImageFromFile()");
00730          return NULL;
00731    }
00732    dls = lookupStatus(sbuf);
00733    if (!dls)
00734    {
00735       dls = allocStatus();
00736    }
00737    if (!dls)
00738    {
00739       error("unable to allocate memory");
00740       return NULL;
00741    }
00742    dls->lib = 0;
00743    if (ofirc == NSObjectFileImageInappropriateFile)
00744    {
00745       if ((dls->lib = dyld_NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR)))
00746       {
00747          debug("Dynamic lib loaded at %ld", dls->lib);
00748          ofi = MAGIC_DYLIB_OFI;
00749          dls->module = MAGIC_DYLIB_MOD;
00750          ofirc = NSObjectFileImageSuccess;
00751          /* Although it is possible with a bit of work to modify this so it works and
00752             functions with RTLD_NOW, I don't deem it necessary at the moment */
00753       }
00754       if (!(dls->module))
00755       {
00756          NSLinkEditError(&ler, &lerno, &file, &errstr);
00757          if (!errstr || (!strlen(errstr)))
00758             error("Can't open this file type");
00759          else
00760             error(errstr);
00761          if ((dls->flags & DL_IN_LIST) == 0)
00762          {
00763             free(dls);
00764          }
00765          return NULL;
00766       }
00767    }
00768    else
00769    {
00770       dls->module = NSLinkModule(ofi, path,
00771                            NSLINKMODULE_OPTION_RETURN_ON_ERROR |
00772                            NSLINKMODULE_OPTION_PRIVATE |
00773                            (isFlagSet(mode, RTLD_NOW) ? NSLINKMODULE_OPTION_BINDNOW : 0));
00774       NSDestroyObjectFileImage(ofi);
00775       if (dls->module)
00776       {
00777          dls->lib = get_mach_header_from_NSModule(dls->module);
00778       }
00779    }
00780    if (!dls->module)
00781    {
00782       NSLinkEditError(&ler, &lerno, &file, &errstr);
00783       if ((dls->flags & DL_IN_LIST) == 0)
00784       {
00785          free(dls);
00786       }
00787       error(errstr);
00788       return NULL;
00789    }
00790 
00791    insertStatus(dls, sbuf);
00792    dls = reference(dls, mode);
00793    if ((init = dlsymIntern(dls, "__init", 0)))
00794    {
00795       debug("calling _init()");
00796       init();
00797    }
00798    return dls;
00799 }

static struct dlstatus * lookupStatus ( const struct stat *  sbuf  )  [static]

Definition at line 403 of file dlfcn.c.

References debug, dlstatus::device, dlstatus::inode, dlstatus::next, and stqueue.

Referenced by dlopen(), and loadModule().

00404 {
00405    struct dlstatus *dls = stqueue;
00406    debug("looking for status");
00407    while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0
00408                || sbuf->st_dev != dls->device || sbuf->st_ino != dls->inode))
00409       dls = dls->next;
00410    return dls;
00411 }

static struct mach_header * my_find_image ( const char *  name  )  [static]

Definition at line 476 of file dlfcn.c.

References dyld_NSAddImage, NSADDIMAGE_OPTION_RETURN_ON_ERROR, and NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED.

Referenced by search_linked_libs().

00477 {
00478    const struct mach_header *mh = 0;
00479    const char *id = NULL;
00480    int i = _dyld_image_count();
00481    int j;
00482    mh = (struct mach_header *)
00483       dyld_NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED |
00484                   NSADDIMAGE_OPTION_RETURN_ON_ERROR);
00485    if (!mh)
00486    {
00487       for (j = 0; j < i; j++)
00488       {
00489          id = _dyld_get_image_name(j);
00490          if (!strcmp(id, name))
00491          {
00492             mh = _dyld_get_image_header(j);
00493             break;
00494          }
00495       }
00496    }
00497    return mh;
00498 }

static int promoteLocalToGlobal ( struct dlstatus dls  )  [static]

Definition at line 442 of file dlfcn.c.

References debug, MAGIC_DYLIB_MOD, and dlstatus::module.

Referenced by reference().

00443 {
00444    static int (*p) (NSModule module) = 0;
00445    debug("promoting");
00446    if (!p)
00447       _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (unsigned long *)&p);
00448    return (dls->module == MAGIC_DYLIB_MOD) || (p && p(dls->module));
00449 }

static void * reference ( struct dlstatus dls,
int  mode 
) [static]

Definition at line 451 of file dlfcn.c.

References debug, error(), isFlagSet(), MAGIC_DYLIB_MOD, dlstatus::mode, dlstatus::module, promoteLocalToGlobal(), dlstatus::refs, RTLD_GLOBAL, and warning().

Referenced by dlopen(), and loadModule().

00452 {
00453    if (dls)
00454    {
00455       if (dls->module == MAGIC_DYLIB_MOD && !isFlagSet(mode, RTLD_GLOBAL))
00456       {
00457          warning("trying to open a .dylib with RTLD_LOCAL");
00458          error("unable to open a .dylib with RTLD_LOCAL");
00459          return NULL;
00460       }
00461       if (isFlagSet(mode, RTLD_GLOBAL) &&
00462          !isFlagSet(dls->mode, RTLD_GLOBAL) && !promoteLocalToGlobal(dls))
00463       {
00464          error("unable to promote local module to global");
00465          return NULL;
00466       }
00467       dls->mode |= mode;
00468       dls->refs++;
00469    }
00470    else
00471       debug("reference called with NULL argument");
00472 
00473    return dls;
00474 }

static void resetdlerror ( void   )  [static]

Definition at line 846 of file dlfcn.c.

References dlerror_key, and dlthread::errset.

Referenced by dladdr(), dlclose(), dlopen(), and dlsymIntern().

00847 {
00848    struct dlthread *tss;
00849    tss = pthread_getspecific(dlerror_key);
00850    tss->errset = 0;
00851 }

static const char * safegetenv ( const char *  s  )  [static]

Definition at line 218 of file dlfcn.c.

Referenced by searchList().

00219 {
00220    const char *ss = getenv(s);
00221    return ss ? ss : "";
00222 }

NSSymbol * search_linked_libs ( const struct mach_header *  mh,
const char *  symbol 
) [static]

Definition at line 506 of file dlfcn.c.

References debug, dyld_NSAddImage, dyld_NSIsSymbolNameDefinedInImage, dyld_NSLookupSymbolInImage, LC_LOAD_WEAK_DYLIB, my_find_image(), NSLOOKUPSYMBOLINIMAGE_OPTION_BIND, and NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR.

Referenced by dlsymIntern().

00507 {
00508    int n;
00509    struct load_command *lc = 0;
00510    struct mach_header *wh;
00511    NSSymbol *nssym = 0;
00512    if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
00513    {
00514       lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
00515       for (n = 0; n < mh->ncmds; n++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
00516       {
00517          if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
00518          {
00519             if ((wh = (struct mach_header *)
00520                 my_find_image((char *)(((struct dylib_command *)lc)->dylib.name.offset +
00521                                  (char *)lc))))
00522             {
00523                if (dyld_NSIsSymbolNameDefinedInImage(wh, symbol))
00524                {
00525                   nssym = dyld_NSLookupSymbolInImage(wh,
00526                                              symbol,
00527                                              NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
00528                                              NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
00529                   break;
00530                }
00531             }
00532          }
00533       }
00534       if ((!nssym) && NSIsSymbolNameDefined(symbol))
00535       {
00536          /* I've never seen this debug message...*/
00537          debug("Symbol \"%s\" is defined but was not found", symbol);
00538       }
00539    }
00540    return nssym;
00541 }

static const char * searchList ( void   )  [static]

Definition at line 278 of file dlfcn.c.

References malloc, and safegetenv().

Referenced by dlcompat_cleanup(), and getSearchPath().

00279 {
00280    size_t buf_size;
00281    static char *buf=NULL;
00282    const char *ldlp = safegetenv("LD_LIBRARY_PATH");
00283    const char *dyldlp = safegetenv("DYLD_LIBRARY_PATH");
00284    const char *stdpath = getenv("DYLD_FALLBACK_LIBRARY_PATH");
00285    if (!stdpath)
00286       stdpath = "/usr/local/lib:/lib:/usr/lib";
00287    if (!buf)
00288    {  
00289       buf_size = strlen(ldlp) + strlen(dyldlp) + strlen(stdpath) + 4;
00290       buf = malloc(buf_size);
00291       snprintf(buf, buf_size, "%s%s%s%s%s%c", dyldlp, (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""),
00292              stdpath, '\0');
00293    }
00294    return buf;
00295 }

static void warning ( const char *  str  )  [static]

Definition at line 211 of file dlfcn.c.

Referenced by dlclose(), dtmf_detect(), loadModule(), mf_detect(), and reference().

00212 {
00213 #if DEBUG > 0
00214    fprintf(stderr, "WARNING: dlcompat: %s\n", str);
00215 #endif
00216 }


Variable Documentation

pthread_mutex_t dlcompat_mutex [static]

Definition at line 105 of file dlfcn.c.

Referenced by dlcompat_cleanup(), dlcompat_init_func(), dolock(), and dounlock().

pthread_key_t dlerror_key [static]

Definition at line 108 of file dlfcn.c.

Referenced by dlcompat_cleanup(), dlcompat_init_func(), dlerror(), dolock(), dounlock(), error(), and resetdlerror().

struct mach_header*(*) dyld_NSAddImage(const char *, unsigned long)=0 [static]

Definition at line 80 of file dlfcn.c.

Referenced by dlcompat_init_func(), loadModule(), my_find_image(), and search_linked_libs().

int(*) dyld_NSIsSymbolNameDefinedInImage(const struct mach_header *, const char *)=0 [static]

Definition at line 81 of file dlfcn.c.

Referenced by dlcompat_init_func(), dlsymIntern(), loadModule(), and search_linked_libs().

NSSymbol(*) dyld_NSLookupSymbolInImage(const struct mach_header *, const char *, unsigned long)=0 [static]

Definition at line 83 of file dlfcn.c.

Referenced by dlcompat_init_func(), dlsymIntern(), loadModule(), and search_linked_libs().

struct dlstatus mainStatus = { 0, MAGIC_DYLIB_MOD, NULL, -1, RTLD_GLOBAL, 0, 0, 0 } [static]

Definition at line 133 of file dlfcn.c.

Referenced by dlcompat_cleanup(), dlopen(), and dlsymIntern().

struct dlstatus* stqueue = &mainStatus [static]

Definition at line 134 of file dlfcn.c.

Referenced by allocStatus(), dlcompat_cleanup(), insertStatus(), isValidStatus(), and lookupStatus().


Generated on Fri Aug 24 02:25:11 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1