Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# dln.c

Go to the documentation of this file.

    00001 /**********************************************************************
    00002
    00003   dln.c -
    00004
    00005   $Author: yugui $
    00006   created at: Tue Jan 18 17:05:06 JST 1994
    00007
    00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
    00009
    00010 **********************************************************************/
    00011
    00012 #ifdef RUBY_EXPORT
    00013 #include "ruby/ruby.h"
    00014 #define dln_notimplement rb_notimplement
    00015 #define dln_memerror rb_memerror
    00016 #define dln_exit rb_exit
    00017 #define dln_loaderror rb_loaderror
    00018 #else
    00019 #define dln_notimplement --->>> dln not implemented <<<---
    00020 #define dln_memerror abort
    00021 #define dln_exit exit
    00022 static void dln_loaderror(const char *format, ...);
    00023 #endif
    00024 #include "dln.h"
    00025
    00026 #ifdef HAVE_STDLIB_H
    00027 # include <stdlib.h>
    00028 #endif
    00029
    00030 #ifdef USE_DLN_A_OUT
    00031 char *dln_argv0;
    00032 #endif
    00033
    00034 #if defined(HAVE_ALLOCA_H)
    00035 #include <alloca.h>
    00036 #endif
    00037
    00038 #ifdef HAVE_STRING_H
    00039 # include <string.h>
    00040 #else
    00041 # include <strings.h>
    00042 #endif
    00043
    00044 #ifndef xmalloc
    00045 void *xmalloc();
    00046 void *xcalloc();
    00047 void *xrealloc();
    00048 #endif
    00049
    00050 #define free(x) xfree(x)
    00051
    00052 #include <stdio.h>
    00053 #if defined(_WIN32)
    00054 #include "missing/file.h"
    00055 #endif
    00056 #include <sys/types.h>
    00057 #include <sys/stat.h>
    00058
    00059 #ifndef S_ISDIR
    00060 #   define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
    00061 #endif
    00062
    00063 #ifdef HAVE_SYS_PARAM_H
    00064 # include <sys/param.h>
    00065 #endif
    00066 #ifndef MAXPATHLEN
    00067 # define MAXPATHLEN 1024
    00068 #endif
    00069
    00070 #ifdef HAVE_UNISTD_H
    00071 # include <unistd.h>
    00072 #endif
    00073
    00074 #ifndef _WIN32
    00075 char *getenv();
    00076 #endif
    00077
    00078 #if defined(__APPLE__) && defined(__MACH__)   /* Mac OS X */
    00079 # if defined(HAVE_DLOPEN)
    00080    /* Mac OS X with dlopen (10.3 or later) */
    00081 #  define MACOSX_DLOPEN
    00082 # else
    00083 #  define MACOSX_DYLD
    00084 # endif
    00085 #endif
    00086
    00087 #if defined(__BEOS__) || defined(__HAIKU__)
    00088 # include <image.h>
    00089 #endif
    00090
    00091 #ifndef dln_loaderror
    00092 static void
    00093 dln_loaderror(const char *format, ...)
    00094 {
    00095     va_list ap;
    00096     va_start(ap, format);
    00097     vfprintf(stderr, format, ap);
    00098     va_end(ap);
    00099     abort();
    00100 }
    00101 #endif
    00102
    00103 #if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT) && !defined(_AIX) && !defined(MACOSX_DYLD) && !defined(_UNICOSMP)
    00104 /* dynamic load with dlopen() */
    00105 # define USE_DLN_DLOPEN
    00106 #endif
    00107
    00108 #ifndef FUNCNAME_PATTERN
    00109 # if defined(__hp9000s300) || ((defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)) && !defined(__ELF__)) || defined(__BORLANDC__) || defined(NeXT) || defined(__WATCOMC__) || defined(MACOSX_DYLD)
    00110 #  define FUNCNAME_PATTERN "_Init_%s"
    00111 # else
    00112 #  define FUNCNAME_PATTERN "Init_%s"
    00113 # endif
    00114 #endif
    00115
    00116 static size_t
    00117 init_funcname_len(char **buf, const char *file)
    00118 {
    00119     char *p;
    00120     const char *slash;
    00121     size_t len;
    00122
    00123     /* Load the file as an object one */
    00124     for (slash = file-1; *file; file++) /* Find position of last '/' */
    00125         if (*file == '/') slash = file;
    00126
    00127     len = strlen(FUNCNAME_PATTERN) + strlen(slash + 1);
    00128     *buf = xmalloc(len);
    00129     snprintf(*buf, len, FUNCNAME_PATTERN, slash + 1);
    00130     for (p = *buf; *p; p++) {         /* Delete suffix if it exists */
    00131         if (*p == '.') {
    00132             *p = '\0'; break;
    00133         }
    00134     }
    00135     return p - *buf;
    00136 }
    00137
    00138 #define init_funcname(buf, file) do {\
    00139     size_t len = init_funcname_len(buf, file);\
    00140     char *tmp = ALLOCA_N(char, len+1);\
    00141     if (!tmp) {\
    00142         free(*buf);\
    00143         dln_memerror();\
    00144     }\
    00145     strlcpy(tmp, *buf, len + 1);\
    00146     free(*buf);\
    00147     *buf = tmp;\
    00148 } while (0)
    00149
    00150 #ifdef USE_DLN_A_OUT
    00151
    00152 #ifndef LIBC_NAME
    00153 # define LIBC_NAME "libc.a"
    00154 #endif
    00155
    00156 #ifndef DLN_DEFAULT_LIB_PATH
    00157 #  define DLN_DEFAULT_LIB_PATH "/lib:/usr/lib:/usr/local/lib:."
    00158 #endif
    00159
    00160 #include <errno.h>
    00161
    00162 static int dln_errno;
    00163
    00164 #define DLN_ENOEXEC     ENOEXEC /* Exec format error */
    00165 #define DLN_ECONFL      1201    /* Symbol name conflict */
    00166 #define DLN_ENOINIT     1202    /* No initializer given */
    00167 #define DLN_EUNDEF      1203    /* Undefine symbol remains */
    00168 #define DLN_ENOTLIB     1204    /* Not a library file */
    00169 #define DLN_EBADLIB     1205    /* Malformed library file */
    00170 #define DLN_EINIT       1206    /* Not initialized */
    00171
    00172 static int dln_init_p = 0;
    00173
    00174 #include <ar.h>
    00175 #include <a.out.h>
    00176 #ifndef N_COMM
    00177 # define N_COMM 0x12
    00178 #endif
    00179 #ifndef N_MAGIC
    00180 # define N_MAGIC(x) (x).a_magic
    00181 #endif
    00182
    00183 #define INVALID_OBJECT(h) (N_MAGIC(h) != OMAGIC)
    00184
    00185 #include "ruby/util.h"
    00186 #include "ruby/st.h"
    00187
    00188 static st_table *sym_tbl;
    00189 static st_table *undef_tbl;
    00190
    00191 static int load_lib();
    00192
    00193 static int
    00194 load_header(int fd, struct exec *hdrp, long disp)
    00195 {
    00196     int size;
    00197
    00198     lseek(fd, disp, 0);
    00199     size = read(fd, hdrp, sizeof(struct exec));
    00200     if (size == -1) {
    00201         dln_errno = errno;
    00202         return -1;
    00203     }
    00204     if (size != sizeof(struct exec) || N_BADMAG(*hdrp)) {
    00205         dln_errno = DLN_ENOEXEC;
    00206         return -1;
    00207     }
    00208     return 0;
    00209 }
    00210
    00211 #if defined(sequent)
    00212 #define RELOC_SYMBOL(r)                 ((r)->r_symbolnum)
    00213 #define RELOC_MEMORY_SUB_P(r)           ((r)->r_bsr)
    00214 #define RELOC_PCREL_P(r)                ((r)->r_pcrel || (r)->r_bsr)
    00215 #define RELOC_TARGET_SIZE(r)            ((r)->r_length)
    00216 #endif
    00217
    00218 /* Default macros */
    00219 #ifndef RELOC_ADDRESS
    00220 #define RELOC_ADDRESS(r)                ((r)->r_address)
    00221 #define RELOC_EXTERN_P(r)               ((r)->r_extern)
    00222 #define RELOC_SYMBOL(r)                 ((r)->r_symbolnum)
    00223 #define RELOC_MEMORY_SUB_P(r)           0
    00224 #define RELOC_PCREL_P(r)                ((r)->r_pcrel)
    00225 #define RELOC_TARGET_SIZE(r)            ((r)->r_length)
    00226 #endif
    00227
    00228 #if defined(sun) && defined(sparc)
    00229 /* Sparc (Sun 4) macros */
    00230 #  undef relocation_info
    00231 #  define relocation_info reloc_info_sparc
    00232 #  define R_RIGHTSHIFT(r)       (reloc_r_rightshift[(r)->r_type])
    00233 #  define R_BITSIZE(r)          (reloc_r_bitsize[(r)->r_type])
    00234 #  define R_LENGTH(r)           (reloc_r_length[(r)->r_type])
    00235 static int reloc_r_rightshift[] = {
    00236   0, 0, 0, 0, 0, 0, 2, 2, 10, 0, 0, 0, 0, 0, 0,
    00237 };
    00238 static int reloc_r_bitsize[] = {
    00239   8, 16, 32, 8, 16, 32, 30, 22, 22, 22, 13, 10, 32, 32, 16,
    00240 };
    00241 static int reloc_r_length[] = {
    00242   0, 1, 2, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    00243 };
    00244 #  define R_PCREL(r) \
    00245     ((r)->r_type >= RELOC_DISP8 && (r)->r_type <= RELOC_WDISP22)
    00246 #  define R_SYMBOL(r) ((r)->r_index)
    00247 #endif
    00248
    00249 #if defined(sequent)
    00250 #define R_SYMBOL(r)             ((r)->r_symbolnum)
    00251 #define R_MEMORY_SUB(r)         ((r)->r_bsr)
    00252 #define R_PCREL(r)              ((r)->r_pcrel || (r)->r_bsr)
    00253 #define R_LENGTH(r)             ((r)->r_length)
    00254 #endif
    00255
    00256 #ifndef R_SYMBOL
    00257 #  define R_SYMBOL(r)           ((r)->r_symbolnum)
    00258 #  define R_MEMORY_SUB(r)       0
    00259 #  define R_PCREL(r)            ((r)->r_pcrel)
    00260 #  define R_LENGTH(r)           ((r)->r_length)
    00261 #endif
    00262
    00263 static struct relocation_info *
    00264 load_reloc(int fd, struct exec *hdrp, long disp)
    00265 {
    00266     struct relocation_info *reloc;
    00267     int size;
    00268
    00269     lseek(fd, disp + N_TXTOFF(*hdrp) + hdrp->a_text + hdrp->a_data, 0);
    00270     size = hdrp->a_trsize + hdrp->a_drsize;
    00271     reloc = (struct relocation_info*)xmalloc(size);
    00272     if (reloc == NULL) {
    00273         dln_errno = errno;
    00274         return NULL;
    00275     }
    00276
    00277     if (read(fd, reloc, size) !=  size) {
    00278         dln_errno = errno;
    00279         free(reloc);
    00280         return NULL;
    00281     }
    00282
    00283     return reloc;
    00284 }
    00285
    00286 static struct nlist *
    00287 load_sym(int fd, struct exec *hdrp, long disp)
    00288 {
    00289     struct nlist * buffer;
    00290     struct nlist * sym;
    00291     struct nlist * end;
    00292     long displ;
    00293     int size;
    00294
    00295     lseek(fd, N_SYMOFF(*hdrp) + hdrp->a_syms + disp, 0);
    00296     if (read(fd, &size, sizeof(int)) != sizeof(int)) {
    00297         goto err_noexec;
    00298     }
    00299
    00300     buffer = (struct nlist*)xmalloc(hdrp->a_syms + size);
    00301     if (buffer == NULL) {
    00302         dln_errno = errno;
    00303         return NULL;
    00304     }
    00305
    00306     lseek(fd, disp + N_SYMOFF(*hdrp), 0);
    00307     if (read(fd, buffer, hdrp->a_syms + size) != hdrp->a_syms + size) {
    00308         free(buffer);
    00309         goto err_noexec;
    00310     }
    00311
    00312     sym = buffer;
    00313     end = sym + hdrp->a_syms / sizeof(struct nlist);
    00314     displ = (long)buffer + (long)(hdrp->a_syms);
    00315
    00316     while (sym < end) {
    00317         sym->n_un.n_name = (char*)sym->n_un.n_strx + displ;
    00318         sym++;
    00319     }
    00320     return buffer;
    00321
    00322   err_noexec:
    00323     dln_errno = DLN_ENOEXEC;
    00324     return NULL;
    00325 }
    00326
    00327 static st_table *
    00328 sym_hash(struct exec *hdrp, struct nlist *syms)
    00329 {
    00330     st_table *tbl;
    00331     struct nlist *sym = syms;
    00332     struct nlist *end = syms + (hdrp->a_syms / sizeof(struct nlist));
    00333
    00334     tbl = st_init_strtable();
    00335     if (tbl == NULL) {
    00336         dln_errno = errno;
    00337         return NULL;
    00338     }
    00339
    00340     while (sym < end) {
    00341         st_insert(tbl, sym->n_un.n_name, sym);
    00342         sym++;
    00343     }
    00344     return tbl;
    00345 }
    00346
    00347 static int
    00348 dln_init(const char *prog)
    00349 {
    00350     char *file, fbuf[MAXPATHLEN];
    00351     int fd;
    00352     struct exec hdr;
    00353     struct nlist *syms;
    00354
    00355     if (dln_init_p == 1) return 0;
    00356
    00357     file = dln_find_exe_r(prog, NULL, fbuf, sizeof(fbuf));
    00358     if (file == NULL || (fd = open(file, O_RDONLY)) < 0) {
    00359         dln_errno = errno;
    00360         return -1;
    00361     }
    00362
    00363     if (load_header(fd, &hdr, 0) == -1) return -1;
    00364     syms = load_sym(fd, &hdr, 0);
    00365     if (syms == NULL) {
    00366         close(fd);
    00367         return -1;
    00368     }
    00369     sym_tbl = sym_hash(&hdr, syms);
    00370     if (sym_tbl == NULL) {      /* file may be start with #! */
    00371         char c = '\0';
    00372         char buf[MAXPATHLEN];
    00373         char *p;
    00374
    00375         free(syms);
    00376         lseek(fd, 0L, 0);
    00377         if (read(fd, &c, 1) == -1) {
    00378             dln_errno = errno;
    00379             return -1;
    00380         }
    00381         if (c != '#') goto err_noexec;
    00382         if (read(fd, &c, 1) == -1) {
    00383             dln_errno = errno;
    00384             return -1;
    00385         }
    00386         if (c != '!') goto err_noexec;
    00387
    00388         p = buf;
    00389         /* skip forwarding spaces */
    00390         while (read(fd, &c, 1) == 1) {
    00391             if (c == '\n') goto err_noexec;
    00392             if (c != '\t' && c != ' ') {
    00393                 *p++ = c;
    00394                 break;
    00395             }
    00396         }
    00397         /* read in command name */
    00398         while (read(fd, p, 1) == 1) {
    00399             if (*p == '\n' || *p == '\t' || *p == ' ') break;
    00400             p++;
    00401             if (p-buf >= MAXPATHLEN) {
    00402                 dln_errno = ENAMETOOLONG;
    00403                 return -1;
    00404             }
    00405         }
    00406         *p = '\0';
    00407
    00408         return dln_init(buf);
    00409     }
    00410     dln_init_p = 1;
    00411     undef_tbl = st_init_strtable();
    00412     close(fd);
    00413     return 0;
    00414
    00415   err_noexec:
    00416     close(fd);
    00417     dln_errno = DLN_ENOEXEC;
    00418     return -1;
    00419 }
    00420
    00421 static long
    00422 load_text_data(int fd, struct exec *hdrp, int bss, long disp)
    00423 {
    00424     int size;
    00425     unsigned char* addr;
    00426
    00427     lseek(fd, disp + N_TXTOFF(*hdrp), 0);
    00428     size = hdrp->a_text + hdrp->a_data;
    00429
    00430     if (bss == -1) size += hdrp->a_bss;
    00431     else if (bss > 1) size += bss;
    00432
    00433     addr = (unsigned char*)xmalloc(size);
    00434     if (addr == NULL) {
    00435         dln_errno = errno;
    00436         return 0;
    00437     }
    00438
    00439     if (read(fd, addr, size) !=  size) {
    00440         dln_errno = errno;
    00441         free(addr);
    00442         return 0;
    00443     }
    00444
    00445     if (bss == -1) {
    00446         memset(addr +  hdrp->a_text + hdrp->a_data, 0, hdrp->a_bss);
    00447     }
    00448     else if (bss > 0) {
    00449         memset(addr +  hdrp->a_text + hdrp->a_data, 0, bss);
    00450     }
    00451
    00452     return (long)addr;
    00453 }
    00454
    00455 static int
    00456 undef_print(char *key, char *value)
    00457 {
    00458     fprintf(stderr, "  %s\n", key);
    00459     return ST_CONTINUE;
    00460 }
    00461
    00462 static void
    00463 dln_print_undef(void)
    00464 {
    00465     fprintf(stderr, " Undefined symbols:\n");
    00466     st_foreach(undef_tbl, undef_print, NULL);
    00467 }
    00468
    00469 static void
    00470 dln_undefined(void)
    00471 {
    00472     if (undef_tbl->num_entries > 0) {
    00473         fprintf(stderr, "dln: Calling undefined function\n");
    00474         dln_print_undef();
    00475         dln_exit(1);
    00476     }
    00477 }
    00478
    00479 struct undef {
    00480     char *name;
    00481     struct relocation_info reloc;
    00482     long base;
    00483     char *addr;
    00484     union {
    00485         char c;
    00486         short s;
    00487         long l;
    00488     } u;
    00489 };
    00490
    00491 static st_table *reloc_tbl = NULL;
    00492 static void
    00493 link_undef(const char *name, long base, struct relocation_info *reloc)
    00494 {
    00495     static int u_no = 0;
    00496     struct undef *obj;
    00497     char *addr = (char*)(reloc->r_address + base);
    00498
    00499     obj = (struct undef*)xmalloc(sizeof(struct undef));
    00500     obj->name = strdup(name);
    00501     obj->reloc = *reloc;
    00502     obj->base = base;
    00503     switch (R_LENGTH(reloc)) {
    00504       case 0:           /* byte */
    00505         obj->u.c = *addr;
    00506         break;
    00507       case 1:           /* word */
    00508         obj->u.s = *(short*)addr;
    00509         break;
    00510       case 2:           /* long */
    00511         obj->u.l = *(long*)addr;
    00512         break;
    00513     }
    00514     if (reloc_tbl == NULL) {
    00515         reloc_tbl = st_init_numtable();
    00516     }
    00517     st_insert(reloc_tbl, u_no++, obj);
    00518 }
    00519
    00520 struct reloc_arg {
    00521     const char *name;
    00522     long value;
    00523 };
    00524
    00525 static int
    00526 reloc_undef(int no, struct undef *undef, struct reloc_arg *arg)
    00527 {
    00528     int datum;
    00529     char *address;
    00530 #if defined(sun) && defined(sparc)
    00531     unsigned int mask = 0;
    00532 #endif
    00533
    00534     if (strcmp(arg->name, undef->name) != 0) return ST_CONTINUE;
    00535     address = (char*)(undef->base + undef->reloc.r_address);
    00536     datum = arg->value;
    00537
    00538     if (R_PCREL(&(undef->reloc))) datum -= undef->base;
    00539 #if defined(sun) && defined(sparc)
    00540     datum += undef->reloc.r_addend;
    00541     datum >>= R_RIGHTSHIFT(&(undef->reloc));
    00542     mask = (1 << R_BITSIZE(&(undef->reloc))) - 1;
    00543     mask |= mask -1;
    00544     datum &= mask;
    00545     switch (R_LENGTH(&(undef->reloc))) {
    00546       case 0:
    00547         *address = undef->u.c;
    00548         *address &= ~mask;
    00549         *address |= datum;
    00550         break;
    00551       case 1:
    00552         *(short *)address = undef->u.s;
    00553         *(short *)address &= ~mask;
    00554         *(short *)address |= datum;
    00555         break;
    00556       case 2:
    00557         *(long *)address = undef->u.l;
    00558         *(long *)address &= ~mask;
    00559         *(long *)address |= datum;
    00560         break;
    00561     }
    00562 #else
    00563     switch (R_LENGTH(&(undef->reloc))) {
    00564       case 0:           /* byte */
    00565         if (R_MEMORY_SUB(&(undef->reloc)))
    00566             *address = datum - *address;
    00567         else *address = undef->u.c + datum;
    00568         break;
    00569       case 1:           /* word */
    00570         if (R_MEMORY_SUB(&(undef->reloc)))
    00571             *(short*)address = datum - *(short*)address;
    00572         else *(short*)address = undef->u.s + datum;
    00573         break;
    00574       case 2:           /* long */
    00575         if (R_MEMORY_SUB(&(undef->reloc)))
    00576             *(long*)address = datum - *(long*)address;
    00577         else *(long*)address = undef->u.l + datum;
    00578         break;
    00579     }
    00580 #endif
    00581     free(undef->name);
    00582     free(undef);
    00583     return ST_DELETE;
    00584 }
    00585
    00586 static void
    00587 unlink_undef(const char *name, long value)
    00588 {
    00589     struct reloc_arg arg;
    00590
    00591     arg.name = name;
    00592     arg.value = value;
    00593     st_foreach(reloc_tbl, reloc_undef, &arg);
    00594 }
    00595
    00596 #ifdef N_INDR
    00597 struct indr_data {
    00598     char *name0, *name1;
    00599 };
    00600
    00601 static int
    00602 reloc_repl(int no, struct undef *undef, struct indr_data *data)
    00603 {
    00604     if (strcmp(data->name0, undef->name) == 0) {
    00605         free(undef->name);
    00606         undef->name = strdup(data->name1);
    00607     }
    00608     return ST_CONTINUE;
    00609 }
    00610 #endif
    00611
    00612 static int
    00613 load_1(int fd, long disp, const char *need_init)
    00614 {
    00615     static const char *libc = LIBC_NAME;
    00616     struct exec hdr;
    00617     struct relocation_info *reloc = NULL;
    00618     long block = 0;
    00619     long new_common = 0; /* Length of new common */
    00620     struct nlist *syms = NULL;
    00621     struct nlist *sym;
    00622     struct nlist *end;
    00623     int init_p = 0;
    00624
    00625     if (load_header(fd, &hdr, disp) == -1) return -1;
    00626     if (INVALID_OBJECT(hdr)) {
    00627         dln_errno = DLN_ENOEXEC;
    00628         return -1;
    00629     }
    00630     reloc = load_reloc(fd, &hdr, disp);
    00631     if (reloc == NULL) return -1;
    00632
    00633     syms = load_sym(fd, &hdr, disp);
    00634     if (syms == NULL) {
    00635         free(reloc);
    00636         return -1;
    00637     }
    00638
    00639     sym = syms;
    00640     end = syms + (hdr.a_syms / sizeof(struct nlist));
    00641     while (sym < end) {
    00642         struct nlist *old_sym;
    00643         int value = sym->n_value;
    00644
    00645 #ifdef N_INDR
    00646         if (sym->n_type == (N_INDR | N_EXT)) {
    00647             char *key = sym->n_un.n_name;
    00648
    00649             if (st_lookup(sym_tbl, sym[1].n_un.n_name, &old_sym)) {
    00650                 if (st_delete(undef_tbl, (st_data_t*)&key, NULL)) {
    00651                     unlink_undef(key, old_sym->n_value);
    00652                     free(key);
    00653                 }
    00654             }
    00655             else {
    00656                 struct indr_data data;
    00657
    00658                 data.name0 = sym->n_un.n_name;
    00659                 data.name1 = sym[1].n_un.n_name;
    00660                 st_foreach(reloc_tbl, reloc_repl, &data);
    00661
    00662                 st_insert(undef_tbl, strdup(sym[1].n_un.n_name), NULL);
    00663                 if (st_delete(undef_tbl, (st_data_t*)&key, NULL)) {
    00664                     free(key);
    00665                 }
    00666             }
    00667             sym += 2;
    00668             continue;
    00669         }
    00670 #endif
    00671         if (sym->n_type == (N_UNDF | N_EXT)) {
    00672             if (st_lookup(sym_tbl, sym->n_un.n_name, &old_sym) == 0) {
    00673                 old_sym = NULL;
    00674             }
    00675
    00676             if (value) {
    00677                 if (old_sym) {
    00678                     sym->n_type = N_EXT | N_COMM;
    00679                     sym->n_value = old_sym->n_value;
    00680                 }
    00681                 else {
    00682                     int rnd =
    00683                         value >= sizeof(double) ? sizeof(double) - 1
    00684                             : value >= sizeof(long) ? sizeof(long) - 1
    00685                                 : sizeof(short) - 1;
    00686
    00687                     sym->n_type = N_COMM;
    00688                     new_common += rnd;
    00689                     new_common &= ~(long)rnd;
    00690                     sym->n_value = new_common;
    00691                     new_common += value;
    00692                 }
    00693             }
    00694             else {
    00695                 if (old_sym) {
    00696                     sym->n_type = N_EXT | N_COMM;
    00697                     sym->n_value = old_sym->n_value;
    00698                 }
    00699                 else {
    00700                     sym->n_value = (long)dln_undefined;
    00701                     st_insert(undef_tbl, strdup(sym->n_un.n_name), NULL);
    00702                 }
    00703             }
    00704         }
    00705         sym++;
    00706     }
    00707
    00708     block = load_text_data(fd, &hdr, hdr.a_bss + new_common, disp);
    00709     if (block == 0) goto err_exit;
    00710
    00711     sym = syms;
    00712     while (sym < end) {
    00713         struct nlist *new_sym;
    00714         char *key;
    00715
    00716         switch (sym->n_type) {
    00717           case N_COMM:
    00718             sym->n_value += hdr.a_text + hdr.a_data;
    00719           case N_TEXT|N_EXT:
    00720           case N_DATA|N_EXT:
    00721
    00722             sym->n_value += block;
    00723
    00724             if (st_lookup(sym_tbl, sym->n_un.n_name, &new_sym) != 0
    00725                 && new_sym->n_value != (long)dln_undefined) {
    00726                 dln_errno = DLN_ECONFL;
    00727                 goto err_exit;
    00728             }
    00729
    00730             key = sym->n_un.n_name;
    00731             if (st_delete(undef_tbl, (st_data_t*)&key, NULL) != 0) {
    00732                 unlink_undef(key, sym->n_value);
    00733                 free(key);
    00734             }
    00735
    00736             new_sym = (struct nlist*)xmalloc(sizeof(struct nlist));
    00737             *new_sym = *sym;
    00738             new_sym->n_un.n_name = strdup(sym->n_un.n_name);
    00739             st_insert(sym_tbl, new_sym->n_un.n_name, new_sym);
    00740             break;
    00741
    00742           case N_TEXT:
    00743           case N_DATA:
    00744             sym->n_value += block;
    00745             break;
    00746         }
    00747         sym++;
    00748     }
    00749
    00750     /*
    00751      * First comes the text-relocation
    00752      */
    00753     {
    00754         struct relocation_info * rel = reloc;
    00755         struct relocation_info * rel_beg = reloc +
    00756             (hdr.a_trsize/sizeof(struct relocation_info));
    00757         struct relocation_info * rel_end = reloc +
    00758             (hdr.a_trsize+hdr.a_drsize)/sizeof(struct relocation_info);
    00759
    00760         while (rel < rel_end) {
    00761             char *address = (char*)(rel->r_address + block);
    00762             long datum = 0;
    00763 #if defined(sun) && defined(sparc)
    00764             unsigned int mask = 0;
    00765 #endif
    00766
    00767             if(rel >= rel_beg)
    00768                 address += hdr.a_text;
    00769
    00770             if (rel->r_extern) { /* Look it up in symbol-table */
    00771                 sym = &(syms[R_SYMBOL(rel)]);
    00772                 switch (sym->n_type) {
    00773                   case N_EXT|N_UNDF:
    00774                     link_undef(sym->n_un.n_name, block, rel);
    00775                   case N_EXT|N_COMM:
    00776                   case N_COMM:
    00777                     datum = sym->n_value;
    00778                     break;
    00779                   default:
    00780                     goto err_exit;
    00781                 }
    00782             } /* end.. look it up */
    00783             else { /* is static */
    00784                 switch (R_SYMBOL(rel)) {
    00785                   case N_TEXT:
    00786                   case N_DATA:
    00787                     datum = block;
    00788                     break;
    00789                   case N_BSS:
    00790                     datum = block +  new_common;
    00791                     break;
    00792                   case N_ABS:
    00793                     break;
    00794                 }
    00795             } /* end .. is static */
    00796             if (R_PCREL(rel)) datum -= block;
    00797
    00798 #if defined(sun) && defined(sparc)
    00799             datum += rel->r_addend;
    00800             datum >>= R_RIGHTSHIFT(rel);
    00801             mask = (1 << R_BITSIZE(rel)) - 1;
    00802             mask |= mask -1;
    00803             datum &= mask;
    00804
    00805             switch (R_LENGTH(rel)) {
    00806               case 0:
    00807                 *address &= ~mask;
    00808                 *address |= datum;
    00809                 break;
    00810               case 1:
    00811                 *(short *)address &= ~mask;
    00812                 *(short *)address |= datum;
    00813                 break;
    00814               case 2:
    00815                 *(long *)address &= ~mask;
    00816                 *(long *)address |= datum;
    00817                 break;
    00818             }
    00819 #else
    00820             switch (R_LENGTH(rel)) {
    00821               case 0:           /* byte */
    00822                 if (datum < -128 || datum > 127) goto err_exit;
    00823                 *address += datum;
    00824                 break;
    00825               case 1:           /* word */
    00826                 *(short *)address += datum;
    00827                 break;
    00828               case 2:           /* long */
    00829                 *(long *)address += datum;
    00830                 break;
    00831             }
    00832 #endif
    00833             rel++;
    00834         }
    00835     }
    00836
    00837     if (need_init) {
    00838         int len;
    00839         char **libs_to_be_linked = 0;
    00840         char *buf;
    00841
    00842         if (undef_tbl->num_entries > 0) {
    00843             if (load_lib(libc) == -1) goto err_exit;
    00844         }
    00845
    00846         init_funcname(&buf, need_init);
    00847         len = strlen(buf);
    00848
    00849         for (sym = syms; sym<end; sym++) {
    00850             char *name = sym->n_un.n_name;
    00851             if (name[0] == '_' && sym->n_value >= block) {
    00852                 if (strcmp(name+1, "dln_libs_to_be_linked") == 0) {
    00853                     libs_to_be_linked = (char**)sym->n_value;
    00854                 }
    00855                 else if (strcmp(name+1, buf) == 0) {
    00856                     init_p = 1;
    00857                     ((int (*)())sym->n_value)();
    00858                 }
    00859             }
    00860         }
    00861         if (libs_to_be_linked && undef_tbl->num_entries > 0) {
    00862             while (*libs_to_be_linked) {
    00863                 load_lib(*libs_to_be_linked);
    00864                 libs_to_be_linked++;
    00865             }
    00866         }
    00867     }
    00868     free(reloc);
    00869     free(syms);
    00870     if (need_init) {
    00871         if (init_p == 0) {
    00872             dln_errno = DLN_ENOINIT;
    00873             return -1;
    00874         }
    00875         if (undef_tbl->num_entries > 0) {
    00876             if (load_lib(libc) == -1) goto err_exit;
    00877             if (undef_tbl->num_entries > 0) {
    00878                 dln_errno = DLN_EUNDEF;
    00879                 return -1;
    00880             }
    00881         }
    00882     }
    00883     return 0;
    00884
    00885   err_exit:
    00886     if (syms) free(syms);
    00887     if (reloc) free(reloc);
    00888     if (block) free((char*)block);
    00889     return -1;
    00890 }
    00891
    00892 static int target_offset;
    00893 static int
    00894 search_undef(const char *key, int value, st_table *lib_tbl)
    00895 {
    00896     long offset;
    00897
    00898     if (st_lookup(lib_tbl, key, &offset) == 0) return ST_CONTINUE;
    00899     target_offset = offset;
    00900     return ST_STOP;
    00901 }
    00902
    00903 struct symdef {
    00904     int rb_str_index;
    00905     int lib_offset;
    00906 };
    00907
    00908 const char *dln_librrb_ary_path = DLN_DEFAULT_LIB_PATH;
    00909
    00910 static int
    00911 load_lib(const char *lib)
    00912 {
    00913     char *path, *file, fbuf[MAXPATHLEN];
    00914     char *envpath = 0;
    00915     char armagic[SARMAG];
    00916     int fd, size;
    00917     struct ar_hdr ahdr;
    00918     st_table *lib_tbl = NULL;
    00919     int *data, nsym;
    00920     struct symdef *base;
    00921     char *name_base;
    00922
    00923     if (dln_init_p == 0) {
    00924         dln_errno = DLN_ENOINIT;
    00925         return -1;
    00926     }
    00927
    00928     if (undef_tbl->num_entries == 0) return 0;
    00929     dln_errno = DLN_EBADLIB;
    00930
    00931     if (lib[0] == '-' && lib[1] == 'l') {
    00932         long len = strlen(lib) + 4;
    00933         char *p = alloca(len);
    00934         snprintf(p, len, "lib%s.a", lib+2);
    00935         lib = p;
    00936     }
    00937
    00938     /* library search path: */
    00939     /* look for environment variable DLN_LIBRARY_PATH first. */
    00940     /* then variable dln_librrb_ary_path. */
    00941     /* if path is still NULL, use "." for path. */
    00942     path = getenv("DLN_LIBRARY_PATH");
    00943     if (path == NULL) path = dln_librrb_ary_path;
    00944     else path = envpath = strdup(path);
    00945
    00946     file = dln_find_file_r(lib, path, fbuf, sizeof(fbuf));
    00947     if (envpath) free(envpath);
    00948     fd = open(file, O_RDONLY);
    00949     if (fd == -1) goto syserr;
    00950     size = read(fd, armagic, SARMAG);
    00951     if (size == -1) goto syserr;
    00952
    00953     if (size != SARMAG) {
    00954         dln_errno = DLN_ENOTLIB;
    00955         goto badlib;
    00956     }
    00957     size = read(fd, &ahdr, sizeof(ahdr));
    00958     if (size == -1) goto syserr;
    00959     if (size != sizeof(ahdr) || sscanf(ahdr.ar_size, "%d", &size) != 1) {
    00960         goto badlib;
    00961     }
    00962
    00963     if (strncmp(ahdr.ar_name, "__.SYMDEF", 9) == 0) {
    00964         /* make hash table from __.SYMDEF */
    00965
    00966         lib_tbl = st_init_strtable();
    00967         data = (int*)xmalloc(size);
    00968         if (data == NULL) goto syserr;
    00969         size = read(fd, data, size);
    00970         nsym = *data / sizeof(struct symdef);
    00971         base = (struct symdef*)(data + 1);
    00972         name_base = (char*)(base + nsym) + sizeof(int);
    00973         while (nsym > 0) {
    00974             char *name = name_base + base->rb_str_index;
    00975
    00976             st_insert(lib_tbl, name, base->lib_offset + sizeof(ahdr));
    00977             nsym--;
    00978             base++;
    00979         }
    00980         for (;;) {
    00981             target_offset = -1;
    00982             st_foreach(undef_tbl, search_undef, lib_tbl);
    00983             if (target_offset == -1) break;
    00984             if (load_1(fd, target_offset, 0) == -1) {
    00985                 st_free_table(lib_tbl);
    00986                 free(data);
    00987                 goto badlib;
    00988             }
    00989             if (undef_tbl->num_entries == 0) break;
    00990         }
    00991         free(data);
    00992         st_free_table(lib_tbl);
    00993     }
    00994     else {
    00995         /* linear library, need to scan (FUTURE) */
    00996
    00997         for (;;) {
    00998             int offset = SARMAG;
    00999             int found = 0;
    01000             struct exec hdr;
    01001             struct nlist *syms, *sym, *end;
    01002
    01003             while (undef_tbl->num_entries > 0) {
    01004                 found = 0;
    01005                 lseek(fd, offset, 0);
    01006                 size = read(fd, &ahdr, sizeof(ahdr));
    01007                 if (size == -1) goto syserr;
    01008                 if (size == 0) break;
    01009                 if (size != sizeof(ahdr)
    01010                     || sscanf(ahdr.ar_size, "%d", &size) != 1) {
    01011                     goto badlib;
    01012                 }
    01013                 offset += sizeof(ahdr);
    01014                 if (load_header(fd, &hdr, offset) == -1)
    01015                     goto badlib;
    01016                 syms = load_sym(fd, &hdr, offset);
    01017                 if (syms == NULL) goto badlib;
    01018                 sym = syms;
    01019                 end = syms + (hdr.a_syms / sizeof(struct nlist));
    01020                 while (sym < end) {
    01021                     if (sym->n_type == N_EXT|N_TEXT
    01022                         && st_lookup(undef_tbl, sym->n_un.n_name, NULL)) {
    01023                         break;
    01024                     }
    01025                     sym++;
    01026                 }
    01027                 if (sym < end) {
    01028                     found++;
    01029                     free(syms);
    01030                     if (load_1(fd, offset, 0) == -1) {
    01031                         goto badlib;
    01032                     }
    01033                 }
    01034                 offset += size;
    01035                 if (offset & 1) offset++;
    01036             }
    01037             if (found) break;
    01038         }
    01039     }
    01040     close(fd);
    01041     return 0;
    01042
    01043   syserr:
    01044     dln_errno = errno;
    01045   badlib:
    01046     if (fd >= 0) close(fd);
    01047     return -1;
    01048 }
    01049
    01050 static int
    01051 load(const char *file)
    01052 {
    01053     int fd;
    01054     int result;
    01055
    01056     if (dln_init_p == 0) {
    01057         if (dln_init(dln_argv0) == -1) return -1;
    01058     }
    01059     result = strlen(file);
    01060     if (file[result-1] == 'a') {
    01061         return load_lib(file);
    01062     }
    01063
    01064     fd = open(file, O_RDONLY);
    01065     if (fd == -1) {
    01066         dln_errno = errno;
    01067         return -1;
    01068     }
    01069     result = load_1(fd, 0, file);
    01070     close(fd);
    01071
    01072     return result;
    01073 }
    01074
    01075 void*
    01076 dln_sym(const char *name)
    01077 {
    01078     struct nlist *sym;
    01079
    01080     if (st_lookup(sym_tbl, name, &sym))
    01081         return (void*)sym->n_value;
    01082     return NULL;
    01083 }
    01084
    01085 #endif /* USE_DLN_A_OUT */
    01086
    01087 #ifdef USE_DLN_DLOPEN
    01088 # include <dlfcn.h>
    01089 #endif
    01090
    01091 #ifdef __hpux
    01092 #include <errno.h>
    01093 #include "dl.h"
    01094 #endif
    01095
    01096 #if defined(_AIX)
    01097 #include <ctype.h>      /* for isdigit()        */
    01098 #include <errno.h>      /* for global errno     */
    01099 #include <sys/ldr.h>
    01100 #endif
    01101
    01102 #ifdef NeXT
    01103 #if NS_TARGET_MAJOR < 4
    01104 #include <mach-o/rld.h>
    01105 #else
    01106 #include <mach-o/dyld.h>
    01107 #ifndef NSLINKMODULE_OPTION_BINDNOW
    01108 #define NSLINKMODULE_OPTION_BINDNOW 1
    01109 #endif
    01110 #endif
    01111 #else
    01112 #ifdef MACOSX_DYLD
    01113 #include <mach-o/dyld.h>
    01114 #endif
    01115 #endif
    01116
    01117 #if defined _WIN32 && !defined __CYGWIN__
    01118 #include <windows.h>
    01119 #endif
    01120
    01121 #if ! defined _AIX
    01122 static const char *
    01123 dln_strerror(void)
    01124 {
    01125 #ifdef USE_DLN_A_OUT
    01126     char *strerror();
    01127
    01128     switch (dln_errno) {
    01129       case DLN_ECONFL:
    01130         return "Symbol name conflict";
    01131       case DLN_ENOINIT:
    01132         return "No initializer given";
    01133       case DLN_EUNDEF:
    01134         return "Unresolved symbols";
    01135       case DLN_ENOTLIB:
    01136         return "Not a library file";
    01137       case DLN_EBADLIB:
    01138         return "Malformed library file";
    01139       case DLN_EINIT:
    01140         return "Not initialized";
    01141       default:
    01142         return strerror(dln_errno);
    01143     }
    01144 #endif
    01145
    01146 #ifdef USE_DLN_DLOPEN
    01147     return (char*)dlerror();
    01148 #endif
    01149
    01150 #if defined _WIN32 && !defined __CYGWIN__
    01151     static char message[1024];
    01152     int error = GetLastError();
    01153     char *p = message;
    01154     p += sprintf(message, "%d: ", error);
    01155     FormatMessage(
    01156         FORMAT_MESSAGE_FROM_SYSTEM       | FORMAT_MESSAGE_IGNORE_INSERTS,
    01157         NULL,
    01158         error,
    01159         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    01160         p,
    01161         sizeof message - strlen(message),
    01162         NULL);
    01163
    01164     for (p = message; *p; p++) {
    01165         if (*p == '\n' || *p == '\r')
    01166             *p = ' ';
    01167     }
    01168     return message;
    01169 #endif
    01170 }
    01171 #endif
    01172
    01173 #if defined(_AIX) && ! defined(_IA64)
    01174 static void
    01175 aix_loaderror(const char *pathname)
    01176 {
    01177   char *message[1024], errbuf[1024];
    01178   int i;
    01179 #define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
    01180   snprintf(errbuf, sizeof(errbuf), "load failed - %s. ", pathname);
    01181
    01182   if (loadquery(L_GETMESSAGES, &message[0], sizeof(message)) != -1) {
    01183     ERRBUF_APPEND("Please issue below command for detailed reasons:\n\t");
    01184     ERRBUF_APPEND("/usr/sbin/execerror ruby ");
    01185     for (i=0; message[i]; i++) {
    01186       ERRBUF_APPEND("\"");
    01187       ERRBUF_APPEND(message[i]);
    01188       ERRBUF_APPEND("\" ");
    01189     }
    01190     ERRBUF_APPEND("\n");
    01191   } else {
    01192     ERRBUF_APPEND(strerror(errno));
    01193     ERRBUF_APPEND("[loadquery failed]");
    01194   }
    01195   dln_loaderror("%s", errbuf);
    01196 }
    01197 #endif
    01198
    01199 #if defined(DLN_NEEDS_ALT_SEPARATOR) && DLN_NEEDS_ALT_SEPARATOR
    01200 #define translit_separator(src) do { \
    01201         char *tmp = ALLOCA_N(char, strlen(src) + 1), *p = tmp, c; \
    01202         do { \
    01203             *p++ = ((c = *file++) == '/') ? DLN_NEEDS_ALT_SEPARATOR : c; \
    01204         } while (c); \
    01205         src = tmp; \
    01206     } while (0)
    01207 #else
    01208 #define translit_separator(str) (void)(str)
    01209 #endif
    01210
    01211 void*
    01212 dln_load(const char *file)
    01213 {
    01214 #if !defined(_AIX) && !defined(NeXT)
    01215     const char *error = 0;
    01216 #define DLN_ERROR() (error = dln_strerror(), strcpy(ALLOCA_N(char, strlen(error) + 1), error))
    01217 #endif
    01218
    01219 #if defined _WIN32 && !defined __CYGWIN__
    01220     HINSTANCE handle;
    01221     char winfile[MAXPATHLEN];
    01222     void (*init_fct)();
    01223     char *buf;
    01224
    01225     if (strlen(file) >= MAXPATHLEN) dln_loaderror("filename too long");
    01226
    01227     /* Load the file as an object one */
    01228     init_funcname(&buf, file);
    01229
    01230     strlcpy(winfile, file, sizeof(winfile));
    01231
    01232     /* Load file */
    01233     if ((handle = LoadLibrary(winfile)) == NULL) {
    01234         error = dln_strerror();
    01235         goto failed;
    01236     }
    01237
    01238     if ((init_fct = (void(*)())GetProcAddress(handle, buf)) == NULL) {
    01239         dln_loaderror("%s - %s\n%s", dln_strerror(), buf, file);
    01240     }
    01241
    01242     /* Call the init code */
    01243     (*init_fct)();
    01244     return handle;
    01245 #else
    01246 #ifdef USE_DLN_A_OUT
    01247     if (load(file) == -1) {
    01248         error = dln_strerror();
    01249         goto failed;
    01250     }
    01251     return 0;
    01252 #else
    01253
    01254     char *buf;
    01255     /* Load the file as an object one */
    01256     init_funcname(&buf, file);
    01257     translit_separator(file);
    01258
    01259 #ifdef USE_DLN_DLOPEN
    01260 #define DLN_DEFINED
    01261     {
    01262         void *handle;
    01263         void (*init_fct)();
    01264
    01265 #ifndef RTLD_LAZY
    01266 # define RTLD_LAZY 1
    01267 #endif
    01268 #ifdef __INTERIX
    01269 # undef RTLD_GLOBAL
    01270 #endif
    01271 #ifndef RTLD_GLOBAL
    01272 # define RTLD_GLOBAL 0
    01273 #endif
    01274
    01275         /* Load file */
    01276         if ((handle = (void*)dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) {
    01277             error = dln_strerror();
    01278             goto failed;
    01279         }
    01280
    01281         init_fct = (void(*)())(VALUE)dlsym(handle, buf);
    01282 #if defined __SYMBIAN32__
    01283         if (init_fct == NULL) {
    01284             init_fct = (void(*)())dlsym(handle, "1"); /* Some Symbian versions do not support symbol table in DLL, ordinal numbers only */
    01285         }
    01286 #endif
    01287         if (init_fct == NULL) {
    01288             error = DLN_ERROR();
    01289             dlclose(handle);
    01290             goto failed;
    01291         }
    01292         /* Call the init code */
    01293         (*init_fct)();
    01294
    01295         return handle;
    01296     }
    01297 #endif /* USE_DLN_DLOPEN */
    01298
    01299 #ifdef __hpux
    01300 #define DLN_DEFINED
    01301     {
    01302         shl_t lib = NULL;
    01303         int flags;
    01304         void (*init_fct)();
    01305
    01306         flags = BIND_DEFERRED;
    01307         lib = shl_load(file, flags, 0);
    01308         if (lib == NULL) {
    01309             extern int errno;
    01310             dln_loaderror("%s - %s", strerror(errno), file);
    01311         }
    01312         shl_findsym(&lib, buf, TYPE_PROCEDURE, (void*)&init_fct);
    01313         if (init_fct == NULL) {
    01314             shl_findsym(&lib, buf, TYPE_UNDEFINED, (void*)&init_fct);
    01315             if (init_fct == NULL) {
    01316                 errno = ENOSYM;
    01317                 dln_loaderror("%s - %s", strerror(ENOSYM), file);
    01318             }
    01319         }
    01320         (*init_fct)();
    01321         return (void*)lib;
    01322     }
    01323 #endif /* hpux */
    01324
    01325 #if defined(_AIX) && ! defined(_IA64)
    01326 #define DLN_DEFINED
    01327     {
    01328         void (*init_fct)();
    01329
    01330         init_fct = (void(*)())load((char*)file, 1, 0);
    01331         if (init_fct == NULL) {
    01332             aix_loaderror(file);
    01333         }
    01334         if (loadbind(0, (void*)dln_load, (void*)init_fct) == -1) {
    01335             aix_loaderror(file);
    01336         }
    01337         (*init_fct)();
    01338         return (void*)init_fct;
    01339     }
    01340 #endif /* _AIX */
    01341
    01342 #if defined(NeXT) || defined(MACOSX_DYLD)
    01343 #define DLN_DEFINED
    01344 /*----------------------------------------------------
    01345    By SHIROYAMA Takayuki Psi@fortune.nest.or.jp
    01346
    01347    Special Thanks...
    01348     Yu tomoak-i@is.aist-nara.ac.jp,
    01349     Mi hisho@tasihara.nest.or.jp,
    01350     sunshine@sunshineco.com,
    01351     and... Miss ARAI Akino(^^;)
    01352  ----------------------------------------------------*/
    01353 #if defined(NeXT) && (NS_TARGET_MAJOR < 4)/* NeXTSTEP rld functions */
    01354
    01355     {
    01356         NXStream* s;
    01357         unsigned long init_address;
    01358         char *object_files[2] = {NULL, NULL};
    01359
    01360         void (*init_fct)();
    01361
    01362         object_files[0] = (char*)file;
    01363
    01364         s = NXOpenFile(2,NX_WRITEONLY);
    01365
    01366         /* Load object file, if return value ==0 ,  load failed*/
    01367         if(rld_load(s, NULL, object_files, NULL) == 0) {
    01368             NXFlush(s);
    01369             NXClose(s);
    01370             dln_loaderror("Failed to load %.200s", file);
    01371         }
    01372
    01373         /* lookup the initial function */
    01374         if(rld_lookup(s, buf, &init_address) == 0) {
    01375             NXFlush(s);
    01376             NXClose(s);
    01377             dln_loaderror("Failed to lookup Init function %.200s", file);
    01378         }
    01379
    01380         NXFlush(s);
    01381         NXClose(s);
    01382
    01383         /* Cannot call *init_address directory, so copy this value to
    01384            function pointer */
    01385         init_fct = (void(*)())init_address;
    01386         (*init_fct)();
    01387         return (void*)init_address;
    01388     }
    01389 #else/* OPENSTEP dyld functions */
    01390     {
    01391         int dyld_result;
    01392         NSObjectFileImage obj_file; /* handle, but not use it */
    01393         /* "file" is module file name .
    01394            "buf" is pointer to initial function name with "_" . */
    01395
    01396         void (*init_fct)();
    01397
    01398
    01399         dyld_result = NSCreateObjectFileImageFromFile(file, &obj_file);
    01400
    01401         if (dyld_result != NSObjectFileImageSuccess) {
    01402             dln_loaderror("Failed to load %.200s", file);
    01403         }
    01404
    01405         NSLinkModule(obj_file, file, NSLINKMODULE_OPTION_BINDNOW);
    01406
    01407         /* lookup the initial function */
    01408         if(!NSIsSymbolNameDefined(buf)) {
    01409             dln_loaderror("Failed to lookup Init function %.200s",file);
    01410         }
    01411         init_fct = NSAddressOfSymbol(NSLookupAndBindSymbol(buf));
    01412         (*init_fct)();
    01413
    01414         return (void*)init_fct;
    01415     }
    01416 #endif /* rld or dyld */
    01417 #endif
    01418
    01419 #if defined(__BEOS__) || defined(__HAIKU__)
    01420 # define DLN_DEFINED
    01421     {
    01422       status_t err_stat;  /* BeOS error status code */
    01423       image_id img_id;    /* extension module unique id */
    01424       void (*init_fct)(); /* initialize function for extension module */
    01425
    01426       /* load extension module */
    01427       img_id = load_add_on(file);
    01428       if (img_id <= 0) {
    01429         dln_loaderror("Failed to load add_on %.200s error_code=%x",
    01430           file, img_id);
    01431       }
    01432
    01433       /* find symbol for module initialize function. */
    01434       /* The Be Book KernelKit Images section described to use
    01435          B_SYMBOL_TYPE_TEXT for symbol of function, not
    01436          B_SYMBOL_TYPE_CODE. Why ? */
    01437       /* strcat(init_fct_symname, "__Fv"); */  /* parameter nothing. */
    01438       /* "__Fv" dont need! The Be Book Bug ? */
    01439       err_stat = get_image_symbol(img_id, buf,
    01440                                   B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
    01441
    01442       if (err_stat != B_NO_ERROR) {
    01443         char real_name[MAXPATHLEN];
    01444
    01445         strlcpy(real_name, buf, MAXPATHLEN);
    01446         strlcat(real_name, "__Fv", MAXPATHLEN);
    01447         err_stat = get_image_symbol(img_id, real_name,
    01448                                     B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
    01449       }
    01450
    01451       if ((B_BAD_IMAGE_ID == err_stat) || (B_BAD_INDEX == err_stat)) {
    01452         unload_add_on(img_id);
    01453         dln_loaderror("Failed to lookup Init function %.200s", file);
    01454       }
    01455       else if (B_NO_ERROR != err_stat) {
    01456         char errmsg[] = "Internal of BeOS version. %.200s (symbol_name = %s)";
    01457         unload_add_on(img_id);
    01458         dln_loaderror(errmsg, strerror(err_stat), buf);
    01459       }
    01460
    01461       /* call module initialize function. */
    01462       (*init_fct)();
    01463       return (void*)img_id;
    01464     }
    01465 #endif /* __BEOS__ || __HAIKU__ */
    01466
    01467 #ifndef DLN_DEFINED
    01468     dln_notimplement();
    01469 #endif
    01470
    01471 #endif /* USE_DLN_A_OUT */
    01472 #endif
    01473 #if !defined(_AIX) && !defined(NeXT)
    01474   failed:
    01475     dln_loaderror("%s - %s", error, file);
    01476 #endif
    01477
    01478     return 0;                   /* dummy return */
    01479 }
    01480