Logo Search packages:      
Sourcecode: sbcl version File versions

ppc-darwin-dlshim.c

/*
 * These functions emulate a small subset of the dlopen / dlsym
 * functionality under Darwin's Mach-O dyld system.
 */

/*
 * This software is part of the SBCL system. See the README file for
 * more information.
 *
 * This software is derived from the CMU CL system, which was
 * written at Carnegie Mellon University and released into the
 * public domain. The software is in the public domain and is
 * provided with absolutely no warranty. See the COPYING and CREDITS
 * files for more information.
 */


#include <mach-o/dyld.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Darwin does not define the standard ELF
 * dlopen/dlclose/dlsym/dlerror interface to shared libraries, so this
 * is an attempt at a minimal wrapper to allow SBCL to work without
 * external dependency on pogma's dlcompat library.
 */

/* For now, there is no RTLD_GLOBAL emulation either. */

static char dl_self; /* I'm going to abuse this */

#define RTLD_LAZY 1
#define RTLD_NOW 2
#define RTLD_GLOBAL 0x100

static int callback_count;
static struct mach_header* last_header;

void dlshim_image_callback(struct mach_header* ptr, unsigned long phooey)
{
    callback_count++;
    last_header = ptr;
}

int lib_path_count(void)
{
    char* libpath;
    int i;
    int count;
    libpath = getenv("DYLD_LIBRARY_PATH");
    count = 1;
    if (libpath) {
      for (i = 0; libpath[i] != '\0'; i++) {
          if (libpath[i] == ':') count++;
      }
    }
    return count;
}

const char* lib_path_prefixify(int index, const char* filename)
{
    static char* retbuf = NULL;
    int fi, li, i, count;
    char* libpath;
    if (!retbuf) {
      retbuf = (char*) malloc(1024*sizeof(char));
    }
    count = 0;
    fi = 0;
    li = -1;
    libpath = getenv("DYLD_LIBRARY_PATH");
    if (libpath) {
      i = 0;
      while (count != index && libpath[i] != '\0') {
          if (libpath[i] == ':') count++;
          i++;
      }
      fi = i;
      while (libpath[i] != '\0' && libpath[i] != ':') {
          i++;
      }
      li = i - 1;
    }
    if (li - fi > 0) {
      if (li - fi + 1 > 1022 - strlen(filename)) {
          retbuf = (char*) realloc(retbuf, (li - fi + 3 + strlen(filename))*sizeof(char));
      }
      memcpy(retbuf, libpath + fi, (li - fi + 1)*sizeof(char));
      retbuf[li - fi + 1] = '/';
      memcpy(retbuf + li - fi + 2, filename, strlen(filename) + 1);
      return retbuf;
    } else {
      return filename;
    }
}

void* dlopen(const char* filename, int flags)
{
    static char has_callback = 0;
    if (!has_callback) {
      _dyld_register_func_for_add_image(dlshim_image_callback);
    }
    if (!filename) {
      return &dl_self;
    } else {
      struct mach_header* img = NULL;
      if (!img) img = NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
      if (!img) img = NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_WITH_SEARCHING);
      if (!img) {
          NSObjectFileImage fileImage;
          callback_count = 0;
          last_header = NULL;
          if (NSCreateObjectFileImageFromFile(filename, &fileImage) == NSObjectFileImageSuccess) {
            NSLinkModule(fileImage, filename, NSLINKMODULE_OPTION_BINDNOW | ((flags & RTLD_GLOBAL)?NSLINKMODULE_OPTION_PRIVATE:0) | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
            if (callback_count && last_header) img = last_header;
          }
      }
      if (!img) {
          NSObjectFileImage fileImage;
          int i, maxi;
          char* prefixfilename;
          maxi = lib_path_count();
          for (i = 0; i < maxi && !img; i++) {
            prefixfilename = lib_path_prefixify(i, filename);
            callback_count = 0;
            last_header = NULL;
            if (NSCreateObjectFileImageFromFile(prefixfilename, &fileImage) == NSObjectFileImageSuccess) {
                NSLinkModule(fileImage, filename, NSLINKMODULE_OPTION_BINDNOW | ((flags & RTLD_GLOBAL)?NSLINKMODULE_OPTION_PRIVATE:0) | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
                if (callback_count && last_header) img = last_header;
            }
          }
      }
      if (img) {
          if (flags & RTLD_NOW) {
            NSLookupSymbolInImage(img, "", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
          }
          if (NSIsSymbolNameDefinedInImage(img, "__init")) {
            NSSymbol* initsymbol;
            void (*initfunc) (void);
            initsymbol = NSLookupSymbolInImage(img, "__init", 0);
            initfunc = NSAddressOfSymbol(initsymbol);
            initfunc();
          }
      }
      return img;
    }
}

const char* dlerror()
{
    static char* errbuf = NULL;
    NSLinkEditErrors a;
    int b;
    char *c, *d;
    NSLinkEditError(&a, &b, &c, &d);
    if (!errbuf) {
      errbuf = (char*) malloc(256*sizeof(char));
    }
    snprintf(errbuf, 255, "%s in %s: %d %d", c, d, a, b);
    return errbuf;
}

void* dlsym(void* handle, char* symbol)
{
    if (handle == &dl_self) {
      if (NSIsSymbolNameDefined(symbol)) {
          NSSymbol* retsym;
          retsym = NSLookupAndBindSymbol(symbol);
          return NSAddressOfSymbol(retsym);
      } else {
          return NULL;
      }
    } else {
      if (NSIsSymbolNameDefinedInImage(handle, symbol)) {
          NSSymbol* retsym;
          retsym = NSLookupSymbolInImage(handle, symbol, 0);
          return NSAddressOfSymbol(retsym);
      } else {
          return NULL;
      }
    }
}

int dlclose(void *handle)
{
    /* dlclose is not implemented, and never will be for dylibs.
     * return -1 to signal an error; it's not used by SBCL anyhow */
    return -1;
}

Generated by  Doxygen 1.6.0   Back to index