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