|
Ruby 1.9.2p290(2011-07-09revision32553)
|
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
1.7.3