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 

Generated on Wed Aug 10 09:13:59 2011 for Ruby by  doxygen 1.4.7