PageRenderTime 55ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/dln.c

https://github.com/diabolo/ruby
C | 1517 lines | 1265 code | 196 blank | 56 comment | 335 complexity | 7d1c6e395ccdad66c6995bb2dd8f5a14 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /**********************************************************************
  2. dln.c -
  3. $Author$
  4. created at: Tue Jan 18 17:05:06 JST 1994
  5. Copyright (C) 1993-2007 Yukihiro Matsumoto
  6. **********************************************************************/
  7. #ifdef RUBY_EXPORT
  8. #include "ruby/ruby.h"
  9. #define dln_notimplement rb_notimplement
  10. #define dln_memerror rb_memerror
  11. #define dln_exit rb_exit
  12. #define dln_loaderror rb_loaderror
  13. #else
  14. #define dln_notimplement --->>> dln not implemented <<<---
  15. #define dln_memerror abort
  16. #define dln_exit exit
  17. static void dln_loaderror(const char *format, ...);
  18. #endif
  19. #include "dln.h"
  20. #ifdef HAVE_STDLIB_H
  21. # include <stdlib.h>
  22. #endif
  23. #ifdef USE_DLN_A_OUT
  24. char *dln_argv0;
  25. #endif
  26. #if defined(HAVE_ALLOCA_H)
  27. #include <alloca.h>
  28. #endif
  29. #ifdef HAVE_STRING_H
  30. # include <string.h>
  31. #else
  32. # include <strings.h>
  33. #endif
  34. #ifndef xmalloc
  35. void *xmalloc();
  36. void *xcalloc();
  37. void *xrealloc();
  38. #endif
  39. #define free(x) xfree(x)
  40. #include <stdio.h>
  41. #if defined(_WIN32)
  42. #include "missing/file.h"
  43. #endif
  44. #include <sys/types.h>
  45. #include <sys/stat.h>
  46. #ifndef S_ISDIR
  47. # define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
  48. #endif
  49. #ifdef HAVE_SYS_PARAM_H
  50. # include <sys/param.h>
  51. #endif
  52. #ifndef MAXPATHLEN
  53. # define MAXPATHLEN 1024
  54. #endif
  55. #ifdef HAVE_UNISTD_H
  56. # include <unistd.h>
  57. #endif
  58. #ifndef _WIN32
  59. char *getenv();
  60. #endif
  61. #if defined(__APPLE__) && defined(__MACH__) /* Mac OS X */
  62. # if defined(HAVE_DLOPEN)
  63. /* Mac OS X with dlopen (10.3 or later) */
  64. # define MACOSX_DLOPEN
  65. # else
  66. # define MACOSX_DYLD
  67. # endif
  68. #endif
  69. #if defined(__BEOS__) || defined(__HAIKU__)
  70. # include <image.h>
  71. #endif
  72. #ifndef dln_loaderror
  73. static void
  74. dln_loaderror(const char *format, ...)
  75. {
  76. va_list ap;
  77. va_start(ap, format);
  78. vfprintf(stderr, format, ap);
  79. va_end(ap);
  80. abort();
  81. }
  82. #endif
  83. #if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT) && !defined(_AIX) && !defined(MACOSX_DYLD) && !defined(_UNICOSMP)
  84. /* dynamic load with dlopen() */
  85. # define USE_DLN_DLOPEN
  86. #endif
  87. #ifndef FUNCNAME_PATTERN
  88. # if defined(__hp9000s300) || ((defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)) && !defined(__ELF__)) || defined(__BORLANDC__) || defined(NeXT) || defined(__WATCOMC__) || defined(MACOSX_DYLD)
  89. # define FUNCNAME_PATTERN "_Init_%s"
  90. # else
  91. # define FUNCNAME_PATTERN "Init_%s"
  92. # endif
  93. #endif
  94. static size_t
  95. init_funcname_len(char **buf, const char *file)
  96. {
  97. char *p;
  98. const char *slash;
  99. size_t len;
  100. /* Load the file as an object one */
  101. for (slash = file-1; *file; file++) /* Find position of last '/' */
  102. if (*file == '/') slash = file;
  103. len = strlen(FUNCNAME_PATTERN) + strlen(slash + 1);
  104. *buf = xmalloc(len);
  105. snprintf(*buf, len, FUNCNAME_PATTERN, slash + 1);
  106. for (p = *buf; *p; p++) { /* Delete suffix if it exists */
  107. if (*p == '.') {
  108. *p = '\0'; break;
  109. }
  110. }
  111. return p - *buf;
  112. }
  113. #define init_funcname(buf, file) do {\
  114. size_t len = init_funcname_len(buf, file);\
  115. char *tmp = ALLOCA_N(char, len+1);\
  116. if (!tmp) {\
  117. free(*buf);\
  118. dln_memerror();\
  119. }\
  120. strlcpy(tmp, *buf, len + 1);\
  121. free(*buf);\
  122. *buf = tmp;\
  123. } while (0)
  124. #ifdef USE_DLN_A_OUT
  125. #ifndef LIBC_NAME
  126. # define LIBC_NAME "libc.a"
  127. #endif
  128. #ifndef DLN_DEFAULT_LIB_PATH
  129. # define DLN_DEFAULT_LIB_PATH "/lib:/usr/lib:/usr/local/lib:."
  130. #endif
  131. #include <errno.h>
  132. static int dln_errno;
  133. #define DLN_ENOEXEC ENOEXEC /* Exec format error */
  134. #define DLN_ECONFL 1201 /* Symbol name conflict */
  135. #define DLN_ENOINIT 1202 /* No initializer given */
  136. #define DLN_EUNDEF 1203 /* Undefine symbol remains */
  137. #define DLN_ENOTLIB 1204 /* Not a library file */
  138. #define DLN_EBADLIB 1205 /* Malformed library file */
  139. #define DLN_EINIT 1206 /* Not initialized */
  140. static int dln_init_p = 0;
  141. #include <ar.h>
  142. #include <a.out.h>
  143. #ifndef N_COMM
  144. # define N_COMM 0x12
  145. #endif
  146. #ifndef N_MAGIC
  147. # define N_MAGIC(x) (x).a_magic
  148. #endif
  149. #define INVALID_OBJECT(h) (N_MAGIC(h) != OMAGIC)
  150. #include "ruby/util.h"
  151. #include "ruby/st.h"
  152. static st_table *sym_tbl;
  153. static st_table *undef_tbl;
  154. static int load_lib();
  155. static int
  156. load_header(int fd, struct exec *hdrp, long disp)
  157. {
  158. int size;
  159. lseek(fd, disp, 0);
  160. size = read(fd, hdrp, sizeof(struct exec));
  161. if (size == -1) {
  162. dln_errno = errno;
  163. return -1;
  164. }
  165. if (size != sizeof(struct exec) || N_BADMAG(*hdrp)) {
  166. dln_errno = DLN_ENOEXEC;
  167. return -1;
  168. }
  169. return 0;
  170. }
  171. #if defined(sequent)
  172. #define RELOC_SYMBOL(r) ((r)->r_symbolnum)
  173. #define RELOC_MEMORY_SUB_P(r) ((r)->r_bsr)
  174. #define RELOC_PCREL_P(r) ((r)->r_pcrel || (r)->r_bsr)
  175. #define RELOC_TARGET_SIZE(r) ((r)->r_length)
  176. #endif
  177. /* Default macros */
  178. #ifndef RELOC_ADDRESS
  179. #define RELOC_ADDRESS(r) ((r)->r_address)
  180. #define RELOC_EXTERN_P(r) ((r)->r_extern)
  181. #define RELOC_SYMBOL(r) ((r)->r_symbolnum)
  182. #define RELOC_MEMORY_SUB_P(r) 0
  183. #define RELOC_PCREL_P(r) ((r)->r_pcrel)
  184. #define RELOC_TARGET_SIZE(r) ((r)->r_length)
  185. #endif
  186. #if defined(sun) && defined(sparc)
  187. /* Sparc (Sun 4) macros */
  188. # undef relocation_info
  189. # define relocation_info reloc_info_sparc
  190. # define R_RIGHTSHIFT(r) (reloc_r_rightshift[(r)->r_type])
  191. # define R_BITSIZE(r) (reloc_r_bitsize[(r)->r_type])
  192. # define R_LENGTH(r) (reloc_r_length[(r)->r_type])
  193. static int reloc_r_rightshift[] = {
  194. 0, 0, 0, 0, 0, 0, 2, 2, 10, 0, 0, 0, 0, 0, 0,
  195. };
  196. static int reloc_r_bitsize[] = {
  197. 8, 16, 32, 8, 16, 32, 30, 22, 22, 22, 13, 10, 32, 32, 16,
  198. };
  199. static int reloc_r_length[] = {
  200. 0, 1, 2, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  201. };
  202. # define R_PCREL(r) \
  203. ((r)->r_type >= RELOC_DISP8 && (r)->r_type <= RELOC_WDISP22)
  204. # define R_SYMBOL(r) ((r)->r_index)
  205. #endif
  206. #if defined(sequent)
  207. #define R_SYMBOL(r) ((r)->r_symbolnum)
  208. #define R_MEMORY_SUB(r) ((r)->r_bsr)
  209. #define R_PCREL(r) ((r)->r_pcrel || (r)->r_bsr)
  210. #define R_LENGTH(r) ((r)->r_length)
  211. #endif
  212. #ifndef R_SYMBOL
  213. # define R_SYMBOL(r) ((r)->r_symbolnum)
  214. # define R_MEMORY_SUB(r) 0
  215. # define R_PCREL(r) ((r)->r_pcrel)
  216. # define R_LENGTH(r) ((r)->r_length)
  217. #endif
  218. static struct relocation_info *
  219. load_reloc(int fd, struct exec *hdrp, long disp)
  220. {
  221. struct relocation_info *reloc;
  222. int size;
  223. lseek(fd, disp + N_TXTOFF(*hdrp) + hdrp->a_text + hdrp->a_data, 0);
  224. size = hdrp->a_trsize + hdrp->a_drsize;
  225. reloc = (struct relocation_info*)xmalloc(size);
  226. if (reloc == NULL) {
  227. dln_errno = errno;
  228. return NULL;
  229. }
  230. if (read(fd, reloc, size) != size) {
  231. dln_errno = errno;
  232. free(reloc);
  233. return NULL;
  234. }
  235. return reloc;
  236. }
  237. static struct nlist *
  238. load_sym(int fd, struct exec *hdrp, long disp)
  239. {
  240. struct nlist * buffer;
  241. struct nlist * sym;
  242. struct nlist * end;
  243. long displ;
  244. int size;
  245. lseek(fd, N_SYMOFF(*hdrp) + hdrp->a_syms + disp, 0);
  246. if (read(fd, &size, sizeof(int)) != sizeof(int)) {
  247. goto err_noexec;
  248. }
  249. buffer = (struct nlist*)xmalloc(hdrp->a_syms + size);
  250. if (buffer == NULL) {
  251. dln_errno = errno;
  252. return NULL;
  253. }
  254. lseek(fd, disp + N_SYMOFF(*hdrp), 0);
  255. if (read(fd, buffer, hdrp->a_syms + size) != hdrp->a_syms + size) {
  256. free(buffer);
  257. goto err_noexec;
  258. }
  259. sym = buffer;
  260. end = sym + hdrp->a_syms / sizeof(struct nlist);
  261. displ = (long)buffer + (long)(hdrp->a_syms);
  262. while (sym < end) {
  263. sym->n_un.n_name = (char*)sym->n_un.n_strx + displ;
  264. sym++;
  265. }
  266. return buffer;
  267. err_noexec:
  268. dln_errno = DLN_ENOEXEC;
  269. return NULL;
  270. }
  271. static st_table *
  272. sym_hash(struct exec *hdrp, struct nlist *syms)
  273. {
  274. st_table *tbl;
  275. struct nlist *sym = syms;
  276. struct nlist *end = syms + (hdrp->a_syms / sizeof(struct nlist));
  277. tbl = st_init_strtable();
  278. if (tbl == NULL) {
  279. dln_errno = errno;
  280. return NULL;
  281. }
  282. while (sym < end) {
  283. st_insert(tbl, sym->n_un.n_name, sym);
  284. sym++;
  285. }
  286. return tbl;
  287. }
  288. static int
  289. dln_init(const char *prog)
  290. {
  291. char *file, fbuf[MAXPATHLEN];
  292. int fd;
  293. struct exec hdr;
  294. struct nlist *syms;
  295. if (dln_init_p == 1) return 0;
  296. file = dln_find_exe_r(prog, NULL, fbuf, sizeof(fbuf));
  297. if (file == NULL || (fd = open(file, O_RDONLY)) < 0) {
  298. dln_errno = errno;
  299. return -1;
  300. }
  301. if (load_header(fd, &hdr, 0) == -1) return -1;
  302. syms = load_sym(fd, &hdr, 0);
  303. if (syms == NULL) {
  304. close(fd);
  305. return -1;
  306. }
  307. sym_tbl = sym_hash(&hdr, syms);
  308. if (sym_tbl == NULL) { /* file may be start with #! */
  309. char c = '\0';
  310. char buf[MAXPATHLEN];
  311. char *p;
  312. free(syms);
  313. lseek(fd, 0L, 0);
  314. if (read(fd, &c, 1) == -1) {
  315. dln_errno = errno;
  316. return -1;
  317. }
  318. if (c != '#') goto err_noexec;
  319. if (read(fd, &c, 1) == -1) {
  320. dln_errno = errno;
  321. return -1;
  322. }
  323. if (c != '!') goto err_noexec;
  324. p = buf;
  325. /* skip forwarding spaces */
  326. while (read(fd, &c, 1) == 1) {
  327. if (c == '\n') goto err_noexec;
  328. if (c != '\t' && c != ' ') {
  329. *p++ = c;
  330. break;
  331. }
  332. }
  333. /* read in command name */
  334. while (read(fd, p, 1) == 1) {
  335. if (*p == '\n' || *p == '\t' || *p == ' ') break;
  336. p++;
  337. if (p-buf >= MAXPATHLEN) {
  338. dln_errno = ENAMETOOLONG;
  339. return -1;
  340. }
  341. }
  342. *p = '\0';
  343. return dln_init(buf);
  344. }
  345. dln_init_p = 1;
  346. undef_tbl = st_init_strtable();
  347. close(fd);
  348. return 0;
  349. err_noexec:
  350. close(fd);
  351. dln_errno = DLN_ENOEXEC;
  352. return -1;
  353. }
  354. static long
  355. load_text_data(int fd, struct exec *hdrp, int bss, long disp)
  356. {
  357. int size;
  358. unsigned char* addr;
  359. lseek(fd, disp + N_TXTOFF(*hdrp), 0);
  360. size = hdrp->a_text + hdrp->a_data;
  361. if (bss == -1) size += hdrp->a_bss;
  362. else if (bss > 1) size += bss;
  363. addr = (unsigned char*)xmalloc(size);
  364. if (addr == NULL) {
  365. dln_errno = errno;
  366. return 0;
  367. }
  368. if (read(fd, addr, size) != size) {
  369. dln_errno = errno;
  370. free(addr);
  371. return 0;
  372. }
  373. if (bss == -1) {
  374. memset(addr + hdrp->a_text + hdrp->a_data, 0, hdrp->a_bss);
  375. }
  376. else if (bss > 0) {
  377. memset(addr + hdrp->a_text + hdrp->a_data, 0, bss);
  378. }
  379. return (long)addr;
  380. }
  381. static int
  382. undef_print(char *key, char *value)
  383. {
  384. fprintf(stderr, " %s\n", key);
  385. return ST_CONTINUE;
  386. }
  387. static void
  388. dln_print_undef(void)
  389. {
  390. fprintf(stderr, " Undefined symbols:\n");
  391. st_foreach(undef_tbl, undef_print, NULL);
  392. }
  393. static void
  394. dln_undefined(void)
  395. {
  396. if (undef_tbl->num_entries > 0) {
  397. fprintf(stderr, "dln: Calling undefined function\n");
  398. dln_print_undef();
  399. dln_exit(1);
  400. }
  401. }
  402. struct undef {
  403. char *name;
  404. struct relocation_info reloc;
  405. long base;
  406. char *addr;
  407. union {
  408. char c;
  409. short s;
  410. long l;
  411. } u;
  412. };
  413. static st_table *reloc_tbl = NULL;
  414. static void
  415. link_undef(const char *name, long base, struct relocation_info *reloc)
  416. {
  417. static int u_no = 0;
  418. struct undef *obj;
  419. char *addr = (char*)(reloc->r_address + base);
  420. obj = (struct undef*)xmalloc(sizeof(struct undef));
  421. obj->name = strdup(name);
  422. obj->reloc = *reloc;
  423. obj->base = base;
  424. switch (R_LENGTH(reloc)) {
  425. case 0: /* byte */
  426. obj->u.c = *addr;
  427. break;
  428. case 1: /* word */
  429. obj->u.s = *(short*)addr;
  430. break;
  431. case 2: /* long */
  432. obj->u.l = *(long*)addr;
  433. break;
  434. }
  435. if (reloc_tbl == NULL) {
  436. reloc_tbl = st_init_numtable();
  437. }
  438. st_insert(reloc_tbl, u_no++, obj);
  439. }
  440. struct reloc_arg {
  441. const char *name;
  442. long value;
  443. };
  444. static int
  445. reloc_undef(int no, struct undef *undef, struct reloc_arg *arg)
  446. {
  447. int datum;
  448. char *address;
  449. #if defined(sun) && defined(sparc)
  450. unsigned int mask = 0;
  451. #endif
  452. if (strcmp(arg->name, undef->name) != 0) return ST_CONTINUE;
  453. address = (char*)(undef->base + undef->reloc.r_address);
  454. datum = arg->value;
  455. if (R_PCREL(&(undef->reloc))) datum -= undef->base;
  456. #if defined(sun) && defined(sparc)
  457. datum += undef->reloc.r_addend;
  458. datum >>= R_RIGHTSHIFT(&(undef->reloc));
  459. mask = (1 << R_BITSIZE(&(undef->reloc))) - 1;
  460. mask |= mask -1;
  461. datum &= mask;
  462. switch (R_LENGTH(&(undef->reloc))) {
  463. case 0:
  464. *address = undef->u.c;
  465. *address &= ~mask;
  466. *address |= datum;
  467. break;
  468. case 1:
  469. *(short *)address = undef->u.s;
  470. *(short *)address &= ~mask;
  471. *(short *)address |= datum;
  472. break;
  473. case 2:
  474. *(long *)address = undef->u.l;
  475. *(long *)address &= ~mask;
  476. *(long *)address |= datum;
  477. break;
  478. }
  479. #else
  480. switch (R_LENGTH(&(undef->reloc))) {
  481. case 0: /* byte */
  482. if (R_MEMORY_SUB(&(undef->reloc)))
  483. *address = datum - *address;
  484. else *address = undef->u.c + datum;
  485. break;
  486. case 1: /* word */
  487. if (R_MEMORY_SUB(&(undef->reloc)))
  488. *(short*)address = datum - *(short*)address;
  489. else *(short*)address = undef->u.s + datum;
  490. break;
  491. case 2: /* long */
  492. if (R_MEMORY_SUB(&(undef->reloc)))
  493. *(long*)address = datum - *(long*)address;
  494. else *(long*)address = undef->u.l + datum;
  495. break;
  496. }
  497. #endif
  498. free(undef->name);
  499. free(undef);
  500. return ST_DELETE;
  501. }
  502. static void
  503. unlink_undef(const char *name, long value)
  504. {
  505. struct reloc_arg arg;
  506. arg.name = name;
  507. arg.value = value;
  508. st_foreach(reloc_tbl, reloc_undef, &arg);
  509. }
  510. #ifdef N_INDR
  511. struct indr_data {
  512. char *name0, *name1;
  513. };
  514. static int
  515. reloc_repl(int no, struct undef *undef, struct indr_data *data)
  516. {
  517. if (strcmp(data->name0, undef->name) == 0) {
  518. free(undef->name);
  519. undef->name = strdup(data->name1);
  520. }
  521. return ST_CONTINUE;
  522. }
  523. #endif
  524. static int
  525. load_1(int fd, long disp, const char *need_init)
  526. {
  527. static const char *libc = LIBC_NAME;
  528. struct exec hdr;
  529. struct relocation_info *reloc = NULL;
  530. long block = 0;
  531. long new_common = 0; /* Length of new common */
  532. struct nlist *syms = NULL;
  533. struct nlist *sym;
  534. struct nlist *end;
  535. int init_p = 0;
  536. if (load_header(fd, &hdr, disp) == -1) return -1;
  537. if (INVALID_OBJECT(hdr)) {
  538. dln_errno = DLN_ENOEXEC;
  539. return -1;
  540. }
  541. reloc = load_reloc(fd, &hdr, disp);
  542. if (reloc == NULL) return -1;
  543. syms = load_sym(fd, &hdr, disp);
  544. if (syms == NULL) {
  545. free(reloc);
  546. return -1;
  547. }
  548. sym = syms;
  549. end = syms + (hdr.a_syms / sizeof(struct nlist));
  550. while (sym < end) {
  551. struct nlist *old_sym;
  552. int value = sym->n_value;
  553. #ifdef N_INDR
  554. if (sym->n_type == (N_INDR | N_EXT)) {
  555. char *key = sym->n_un.n_name;
  556. if (st_lookup(sym_tbl, sym[1].n_un.n_name, &old_sym)) {
  557. if (st_delete(undef_tbl, (st_data_t*)&key, NULL)) {
  558. unlink_undef(key, old_sym->n_value);
  559. free(key);
  560. }
  561. }
  562. else {
  563. struct indr_data data;
  564. data.name0 = sym->n_un.n_name;
  565. data.name1 = sym[1].n_un.n_name;
  566. st_foreach(reloc_tbl, reloc_repl, &data);
  567. st_insert(undef_tbl, strdup(sym[1].n_un.n_name), NULL);
  568. if (st_delete(undef_tbl, (st_data_t*)&key, NULL)) {
  569. free(key);
  570. }
  571. }
  572. sym += 2;
  573. continue;
  574. }
  575. #endif
  576. if (sym->n_type == (N_UNDF | N_EXT)) {
  577. if (st_lookup(sym_tbl, sym->n_un.n_name, &old_sym) == 0) {
  578. old_sym = NULL;
  579. }
  580. if (value) {
  581. if (old_sym) {
  582. sym->n_type = N_EXT | N_COMM;
  583. sym->n_value = old_sym->n_value;
  584. }
  585. else {
  586. int rnd =
  587. value >= sizeof(double) ? sizeof(double) - 1
  588. : value >= sizeof(long) ? sizeof(long) - 1
  589. : sizeof(short) - 1;
  590. sym->n_type = N_COMM;
  591. new_common += rnd;
  592. new_common &= ~(long)rnd;
  593. sym->n_value = new_common;
  594. new_common += value;
  595. }
  596. }
  597. else {
  598. if (old_sym) {
  599. sym->n_type = N_EXT | N_COMM;
  600. sym->n_value = old_sym->n_value;
  601. }
  602. else {
  603. sym->n_value = (long)dln_undefined;
  604. st_insert(undef_tbl, strdup(sym->n_un.n_name), NULL);
  605. }
  606. }
  607. }
  608. sym++;
  609. }
  610. block = load_text_data(fd, &hdr, hdr.a_bss + new_common, disp);
  611. if (block == 0) goto err_exit;
  612. sym = syms;
  613. while (sym < end) {
  614. struct nlist *new_sym;
  615. char *key;
  616. switch (sym->n_type) {
  617. case N_COMM:
  618. sym->n_value += hdr.a_text + hdr.a_data;
  619. case N_TEXT|N_EXT:
  620. case N_DATA|N_EXT:
  621. sym->n_value += block;
  622. if (st_lookup(sym_tbl, sym->n_un.n_name, &new_sym) != 0
  623. && new_sym->n_value != (long)dln_undefined) {
  624. dln_errno = DLN_ECONFL;
  625. goto err_exit;
  626. }
  627. key = sym->n_un.n_name;
  628. if (st_delete(undef_tbl, (st_data_t*)&key, NULL) != 0) {
  629. unlink_undef(key, sym->n_value);
  630. free(key);
  631. }
  632. new_sym = (struct nlist*)xmalloc(sizeof(struct nlist));
  633. *new_sym = *sym;
  634. new_sym->n_un.n_name = strdup(sym->n_un.n_name);
  635. st_insert(sym_tbl, new_sym->n_un.n_name, new_sym);
  636. break;
  637. case N_TEXT:
  638. case N_DATA:
  639. sym->n_value += block;
  640. break;
  641. }
  642. sym++;
  643. }
  644. /*
  645. * First comes the text-relocation
  646. */
  647. {
  648. struct relocation_info * rel = reloc;
  649. struct relocation_info * rel_beg = reloc +
  650. (hdr.a_trsize/sizeof(struct relocation_info));
  651. struct relocation_info * rel_end = reloc +
  652. (hdr.a_trsize+hdr.a_drsize)/sizeof(struct relocation_info);
  653. while (rel < rel_end) {
  654. char *address = (char*)(rel->r_address + block);
  655. long datum = 0;
  656. #if defined(sun) && defined(sparc)
  657. unsigned int mask = 0;
  658. #endif
  659. if(rel >= rel_beg)
  660. address += hdr.a_text;
  661. if (rel->r_extern) { /* Look it up in symbol-table */
  662. sym = &(syms[R_SYMBOL(rel)]);
  663. switch (sym->n_type) {
  664. case N_EXT|N_UNDF:
  665. link_undef(sym->n_un.n_name, block, rel);
  666. case N_EXT|N_COMM:
  667. case N_COMM:
  668. datum = sym->n_value;
  669. break;
  670. default:
  671. goto err_exit;
  672. }
  673. } /* end.. look it up */
  674. else { /* is static */
  675. switch (R_SYMBOL(rel)) {
  676. case N_TEXT:
  677. case N_DATA:
  678. datum = block;
  679. break;
  680. case N_BSS:
  681. datum = block + new_common;
  682. break;
  683. case N_ABS:
  684. break;
  685. }
  686. } /* end .. is static */
  687. if (R_PCREL(rel)) datum -= block;
  688. #if defined(sun) && defined(sparc)
  689. datum += rel->r_addend;
  690. datum >>= R_RIGHTSHIFT(rel);
  691. mask = (1 << R_BITSIZE(rel)) - 1;
  692. mask |= mask -1;
  693. datum &= mask;
  694. switch (R_LENGTH(rel)) {
  695. case 0:
  696. *address &= ~mask;
  697. *address |= datum;
  698. break;
  699. case 1:
  700. *(short *)address &= ~mask;
  701. *(short *)address |= datum;
  702. break;
  703. case 2:
  704. *(long *)address &= ~mask;
  705. *(long *)address |= datum;
  706. break;
  707. }
  708. #else
  709. switch (R_LENGTH(rel)) {
  710. case 0: /* byte */
  711. if (datum < -128 || datum > 127) goto err_exit;
  712. *address += datum;
  713. break;
  714. case 1: /* word */
  715. *(short *)address += datum;
  716. break;
  717. case 2: /* long */
  718. *(long *)address += datum;
  719. break;
  720. }
  721. #endif
  722. rel++;
  723. }
  724. }
  725. if (need_init) {
  726. int len;
  727. char **libs_to_be_linked = 0;
  728. char *buf;
  729. if (undef_tbl->num_entries > 0) {
  730. if (load_lib(libc) == -1) goto err_exit;
  731. }
  732. init_funcname(&buf, need_init);
  733. len = strlen(buf);
  734. for (sym = syms; sym<end; sym++) {
  735. char *name = sym->n_un.n_name;
  736. if (name[0] == '_' && sym->n_value >= block) {
  737. if (strcmp(name+1, "dln_libs_to_be_linked") == 0) {
  738. libs_to_be_linked = (char**)sym->n_value;
  739. }
  740. else if (strcmp(name+1, buf) == 0) {
  741. init_p = 1;
  742. ((int (*)())sym->n_value)();
  743. }
  744. }
  745. }
  746. if (libs_to_be_linked && undef_tbl->num_entries > 0) {
  747. while (*libs_to_be_linked) {
  748. load_lib(*libs_to_be_linked);
  749. libs_to_be_linked++;
  750. }
  751. }
  752. }
  753. free(reloc);
  754. free(syms);
  755. if (need_init) {
  756. if (init_p == 0) {
  757. dln_errno = DLN_ENOINIT;
  758. return -1;
  759. }
  760. if (undef_tbl->num_entries > 0) {
  761. if (load_lib(libc) == -1) goto err_exit;
  762. if (undef_tbl->num_entries > 0) {
  763. dln_errno = DLN_EUNDEF;
  764. return -1;
  765. }
  766. }
  767. }
  768. return 0;
  769. err_exit:
  770. if (syms) free(syms);
  771. if (reloc) free(reloc);
  772. if (block) free((char*)block);
  773. return -1;
  774. }
  775. static int target_offset;
  776. static int
  777. search_undef(const char *key, int value, st_table *lib_tbl)
  778. {
  779. long offset;
  780. if (st_lookup(lib_tbl, key, &offset) == 0) return ST_CONTINUE;
  781. target_offset = offset;
  782. return ST_STOP;
  783. }
  784. struct symdef {
  785. int rb_str_index;
  786. int lib_offset;
  787. };
  788. const char *dln_librrb_ary_path = DLN_DEFAULT_LIB_PATH;
  789. static int
  790. load_lib(const char *lib)
  791. {
  792. char *path, *file, fbuf[MAXPATHLEN];
  793. char *envpath = 0;
  794. char armagic[SARMAG];
  795. int fd, size;
  796. struct ar_hdr ahdr;
  797. st_table *lib_tbl = NULL;
  798. int *data, nsym;
  799. struct symdef *base;
  800. char *name_base;
  801. if (dln_init_p == 0) {
  802. dln_errno = DLN_ENOINIT;
  803. return -1;
  804. }
  805. if (undef_tbl->num_entries == 0) return 0;
  806. dln_errno = DLN_EBADLIB;
  807. if (lib[0] == '-' && lib[1] == 'l') {
  808. long len = strlen(lib) + 4;
  809. char *p = alloca(len);
  810. snprintf(p, len, "lib%s.a", lib+2);
  811. lib = p;
  812. }
  813. /* library search path: */
  814. /* look for environment variable DLN_LIBRARY_PATH first. */
  815. /* then variable dln_librrb_ary_path. */
  816. /* if path is still NULL, use "." for path. */
  817. path = getenv("DLN_LIBRARY_PATH");
  818. if (path == NULL) path = dln_librrb_ary_path;
  819. else path = envpath = strdup(path);
  820. file = dln_find_file_r(lib, path, fbuf, sizeof(fbuf));
  821. if (envpath) free(envpath);
  822. fd = open(file, O_RDONLY);
  823. if (fd == -1) goto syserr;
  824. size = read(fd, armagic, SARMAG);
  825. if (size == -1) goto syserr;
  826. if (size != SARMAG) {
  827. dln_errno = DLN_ENOTLIB;
  828. goto badlib;
  829. }
  830. size = read(fd, &ahdr, sizeof(ahdr));
  831. if (size == -1) goto syserr;
  832. if (size != sizeof(ahdr) || sscanf(ahdr.ar_size, "%d", &size) != 1) {
  833. goto badlib;
  834. }
  835. if (strncmp(ahdr.ar_name, "__.SYMDEF", 9) == 0) {
  836. /* make hash table from __.SYMDEF */
  837. lib_tbl = st_init_strtable();
  838. data = (int*)xmalloc(size);
  839. if (data == NULL) goto syserr;
  840. size = read(fd, data, size);
  841. nsym = *data / sizeof(struct symdef);
  842. base = (struct symdef*)(data + 1);
  843. name_base = (char*)(base + nsym) + sizeof(int);
  844. while (nsym > 0) {
  845. char *name = name_base + base->rb_str_index;
  846. st_insert(lib_tbl, name, base->lib_offset + sizeof(ahdr));
  847. nsym--;
  848. base++;
  849. }
  850. for (;;) {
  851. target_offset = -1;
  852. st_foreach(undef_tbl, search_undef, lib_tbl);
  853. if (target_offset == -1) break;
  854. if (load_1(fd, target_offset, 0) == -1) {
  855. st_free_table(lib_tbl);
  856. free(data);
  857. goto badlib;
  858. }
  859. if (undef_tbl->num_entries == 0) break;
  860. }
  861. free(data);
  862. st_free_table(lib_tbl);
  863. }
  864. else {
  865. /* linear library, need to scan (FUTURE) */
  866. for (;;) {
  867. int offset = SARMAG;
  868. int found = 0;
  869. struct exec hdr;
  870. struct nlist *syms, *sym, *end;
  871. while (undef_tbl->num_entries > 0) {
  872. found = 0;
  873. lseek(fd, offset, 0);
  874. size = read(fd, &ahdr, sizeof(ahdr));
  875. if (size == -1) goto syserr;
  876. if (size == 0) break;
  877. if (size != sizeof(ahdr)
  878. || sscanf(ahdr.ar_size, "%d", &size) != 1) {
  879. goto badlib;
  880. }
  881. offset += sizeof(ahdr);
  882. if (load_header(fd, &hdr, offset) == -1)
  883. goto badlib;
  884. syms = load_sym(fd, &hdr, offset);
  885. if (syms == NULL) goto badlib;
  886. sym = syms;
  887. end = syms + (hdr.a_syms / sizeof(struct nlist));
  888. while (sym < end) {
  889. if (sym->n_type == N_EXT|N_TEXT
  890. && st_lookup(undef_tbl, sym->n_un.n_name, NULL)) {
  891. break;
  892. }
  893. sym++;
  894. }
  895. if (sym < end) {
  896. found++;
  897. free(syms);
  898. if (load_1(fd, offset, 0) == -1) {
  899. goto badlib;
  900. }
  901. }
  902. offset += size;
  903. if (offset & 1) offset++;
  904. }
  905. if (found) break;
  906. }
  907. }
  908. close(fd);
  909. return 0;
  910. syserr:
  911. dln_errno = errno;
  912. badlib:
  913. if (fd >= 0) close(fd);
  914. return -1;
  915. }
  916. static int
  917. load(const char *file)
  918. {
  919. int fd;
  920. int result;
  921. if (dln_init_p == 0) {
  922. if (dln_init(dln_argv0) == -1) return -1;
  923. }
  924. result = strlen(file);
  925. if (file[result-1] == 'a') {
  926. return load_lib(file);
  927. }
  928. fd = open(file, O_RDONLY);
  929. if (fd == -1) {
  930. dln_errno = errno;
  931. return -1;
  932. }
  933. result = load_1(fd, 0, file);
  934. close(fd);
  935. return result;
  936. }
  937. void*
  938. dln_sym(const char *name)
  939. {
  940. struct nlist *sym;
  941. if (st_lookup(sym_tbl, name, &sym))
  942. return (void*)sym->n_value;
  943. return NULL;
  944. }
  945. #endif /* USE_DLN_A_OUT */
  946. #ifdef USE_DLN_DLOPEN
  947. # include <dlfcn.h>
  948. #endif
  949. #ifdef __hpux
  950. #include <errno.h>
  951. #include "dl.h"
  952. #endif
  953. #if defined(_AIX)
  954. #include <ctype.h> /* for isdigit() */
  955. #include <errno.h> /* for global errno */
  956. #include <sys/ldr.h>
  957. #endif
  958. #ifdef NeXT
  959. #if NS_TARGET_MAJOR < 4
  960. #include <mach-o/rld.h>
  961. #else
  962. #include <mach-o/dyld.h>
  963. #ifndef NSLINKMODULE_OPTION_BINDNOW
  964. #define NSLINKMODULE_OPTION_BINDNOW 1
  965. #endif
  966. #endif
  967. #else
  968. #ifdef MACOSX_DYLD
  969. #include <mach-o/dyld.h>
  970. #endif
  971. #endif
  972. #if defined _WIN32 && !defined __CYGWIN__
  973. #include <windows.h>
  974. #include <imagehlp.h>
  975. #endif
  976. #if defined _WIN32 && !defined __CYGWIN__
  977. static const char *
  978. dln_strerror(char *message, size_t size)
  979. {
  980. int error = GetLastError();
  981. char *p = message;
  982. size_t len = snprintf(message, size, "%d: ", error);
  983. FormatMessage(
  984. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  985. NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  986. message + len, size - len, NULL);
  987. for (p = message + len; *p; p++) {
  988. if (*p == '\n' || *p == '\r')
  989. *p = ' ';
  990. }
  991. return message;
  992. }
  993. #define dln_strerror() dln_strerror(message, sizeof message)
  994. #elif ! defined _AIX
  995. static const char *
  996. dln_strerror(void)
  997. {
  998. #ifdef USE_DLN_A_OUT
  999. char *strerror();
  1000. switch (dln_errno) {
  1001. case DLN_ECONFL:
  1002. return "Symbol name conflict";
  1003. case DLN_ENOINIT:
  1004. return "No initializer given";
  1005. case DLN_EUNDEF:
  1006. return "Unresolved symbols";
  1007. case DLN_ENOTLIB:
  1008. return "Not a library file";
  1009. case DLN_EBADLIB:
  1010. return "Malformed library file";
  1011. case DLN_EINIT:
  1012. return "Not initialized";
  1013. default:
  1014. return strerror(dln_errno);
  1015. }
  1016. #endif
  1017. #ifdef USE_DLN_DLOPEN
  1018. return (char*)dlerror();
  1019. #endif
  1020. }
  1021. #endif
  1022. #if defined(_AIX) && ! defined(_IA64)
  1023. static void
  1024. aix_loaderror(const char *pathname)
  1025. {
  1026. char *message[1024], errbuf[1024];
  1027. int i;
  1028. #define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
  1029. snprintf(errbuf, sizeof(errbuf), "load failed - %s. ", pathname);
  1030. if (loadquery(L_GETMESSAGES, &message[0], sizeof(message)) != -1) {
  1031. ERRBUF_APPEND("Please issue below command for detailed reasons:\n\t");
  1032. ERRBUF_APPEND("/usr/sbin/execerror ruby ");
  1033. for (i=0; message[i]; i++) {
  1034. ERRBUF_APPEND("\"");
  1035. ERRBUF_APPEND(message[i]);
  1036. ERRBUF_APPEND("\" ");
  1037. }
  1038. ERRBUF_APPEND("\n");
  1039. } else {
  1040. ERRBUF_APPEND(strerror(errno));
  1041. ERRBUF_APPEND("[loadquery failed]");
  1042. }
  1043. dln_loaderror("%s", errbuf);
  1044. }
  1045. #endif
  1046. #if defined _WIN32 && defined RUBY_EXPORT
  1047. HANDLE rb_libruby_handle(void);
  1048. static int
  1049. rb_w32_check_imported(HMODULE ext, HMODULE mine)
  1050. {
  1051. ULONG size;
  1052. const IMAGE_IMPORT_DESCRIPTOR *desc;
  1053. desc = ImageDirectoryEntryToData(ext, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size);
  1054. if (!desc) return 0;
  1055. while (desc->Name) {
  1056. PIMAGE_THUNK_DATA pint = (PIMAGE_THUNK_DATA)((char *)ext + desc->Characteristics);
  1057. PIMAGE_THUNK_DATA piat = (PIMAGE_THUNK_DATA)((char *)ext + desc->FirstThunk);
  1058. while (piat->u1.Function) {
  1059. PIMAGE_IMPORT_BY_NAME pii = (PIMAGE_IMPORT_BY_NAME)((char *)ext + (size_t)pint->u1.AddressOfData);
  1060. static const char prefix[] = "rb_";
  1061. if (strncmp(pii->Name, prefix, sizeof(prefix) - 1) == 0) {
  1062. FARPROC addr = GetProcAddress(mine, pii->Name);
  1063. if (addr) return (FARPROC)piat->u1.Function == addr;
  1064. }
  1065. piat++;
  1066. pint++;
  1067. }
  1068. desc++;
  1069. }
  1070. return 1;
  1071. }
  1072. #endif
  1073. #if defined(DLN_NEEDS_ALT_SEPARATOR) && DLN_NEEDS_ALT_SEPARATOR
  1074. #define translit_separator(src) do { \
  1075. char *tmp = ALLOCA_N(char, strlen(src) + 1), *p = tmp, c; \
  1076. do { \
  1077. *p++ = ((c = *file++) == '/') ? DLN_NEEDS_ALT_SEPARATOR : c; \
  1078. } while (c); \
  1079. src = tmp; \
  1080. } while (0)
  1081. #else
  1082. #define translit_separator(str) (void)(str)
  1083. #endif
  1084. void*
  1085. dln_load(const char *file)
  1086. {
  1087. #if !defined(_AIX) && !defined(NeXT)
  1088. const char *error = 0;
  1089. #define DLN_ERROR() (error = dln_strerror(), strcpy(ALLOCA_N(char, strlen(error) + 1), error))
  1090. #endif
  1091. #if defined _WIN32 && !defined __CYGWIN__
  1092. HINSTANCE handle;
  1093. char winfile[MAXPATHLEN];
  1094. char message[1024];
  1095. void (*init_fct)();
  1096. char *buf;
  1097. if (strlen(file) >= MAXPATHLEN) dln_loaderror("filename too long");
  1098. /* Load the file as an object one */
  1099. init_funcname(&buf, file);
  1100. strlcpy(winfile, file, sizeof(winfile));
  1101. /* Load file */
  1102. if ((handle = LoadLibrary(winfile)) == NULL) {
  1103. error = dln_strerror();
  1104. goto failed;
  1105. }
  1106. #if defined _WIN32 && defined RUBY_EXPORT
  1107. if (!rb_w32_check_imported(handle, rb_libruby_handle())) {
  1108. FreeLibrary(handle);
  1109. error = "incompatible library version";
  1110. goto failed;
  1111. }
  1112. #endif
  1113. if ((init_fct = (void(*)())GetProcAddress(handle, buf)) == NULL) {
  1114. dln_loaderror("%s - %s\n%s", dln_strerror(), buf, file);
  1115. }
  1116. /* Call the init code */
  1117. (*init_fct)();
  1118. return handle;
  1119. #else
  1120. #ifdef USE_DLN_A_OUT
  1121. if (load(file) == -1) {
  1122. error = dln_strerror();
  1123. goto failed;
  1124. }
  1125. return 0;
  1126. #else
  1127. char *buf;
  1128. /* Load the file as an object one */
  1129. init_funcname(&buf, file);
  1130. translit_separator(file);
  1131. #ifdef USE_DLN_DLOPEN
  1132. #define DLN_DEFINED
  1133. {
  1134. void *handle;
  1135. void (*init_fct)();
  1136. #ifndef RTLD_LAZY
  1137. # define RTLD_LAZY 1
  1138. #endif
  1139. #ifdef __INTERIX
  1140. # undef RTLD_GLOBAL
  1141. #endif
  1142. #ifndef RTLD_GLOBAL
  1143. # define RTLD_GLOBAL 0
  1144. #endif
  1145. /* Load file */
  1146. if ((handle = (void*)dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) {
  1147. error = dln_strerror();
  1148. goto failed;
  1149. }
  1150. init_fct = (void(*)())(VALUE)dlsym(handle, buf);
  1151. #if defined __SYMBIAN32__
  1152. if (init_fct == NULL) {
  1153. init_fct = (void(*)())dlsym(handle, "1"); /* Some Symbian versions do not support symbol table in DLL, ordinal numbers only */
  1154. }
  1155. #endif
  1156. if (init_fct == NULL) {
  1157. error = DLN_ERROR();
  1158. dlclose(handle);
  1159. goto failed;
  1160. }
  1161. /* Call the init code */
  1162. (*init_fct)();
  1163. return handle;
  1164. }
  1165. #endif /* USE_DLN_DLOPEN */
  1166. #ifdef __hpux
  1167. #define DLN_DEFINED
  1168. {
  1169. shl_t lib = NULL;
  1170. int flags;
  1171. void (*init_fct)();
  1172. flags = BIND_DEFERRED;
  1173. lib = shl_load(file, flags, 0);
  1174. if (lib == NULL) {
  1175. extern int errno;
  1176. dln_loaderror("%s - %s", strerror(errno), file);
  1177. }
  1178. shl_findsym(&lib, buf, TYPE_PROCEDURE, (void*)&init_fct);
  1179. if (init_fct == NULL) {
  1180. shl_findsym(&lib, buf, TYPE_UNDEFINED, (void*)&init_fct);
  1181. if (init_fct == NULL) {
  1182. errno = ENOSYM;
  1183. dln_loaderror("%s - %s", strerror(ENOSYM), file);
  1184. }
  1185. }
  1186. (*init_fct)();
  1187. return (void*)lib;
  1188. }
  1189. #endif /* hpux */
  1190. #if defined(_AIX) && ! defined(_IA64)
  1191. #define DLN_DEFINED
  1192. {
  1193. void (*init_fct)();
  1194. init_fct = (void(*)())load((char*)file, 1, 0);
  1195. if (init_fct == NULL) {
  1196. aix_loaderror(file);
  1197. }
  1198. if (loadbind(0, (void*)dln_load, (void*)init_fct) == -1) {
  1199. aix_loaderror(file);
  1200. }
  1201. (*init_fct)();
  1202. return (void*)init_fct;
  1203. }
  1204. #endif /* _AIX */
  1205. #if defined(NeXT) || defined(MACOSX_DYLD)
  1206. #define DLN_DEFINED
  1207. /*----------------------------------------------------
  1208. By SHIROYAMA Takayuki Psi@fortune.nest.or.jp
  1209. Special Thanks...
  1210. Yu tomoak-i@is.aist-nara.ac.jp,
  1211. Mi hisho@tasihara.nest.or.jp,
  1212. sunshine@sunshineco.com,
  1213. and... Miss ARAI Akino(^^;)
  1214. ----------------------------------------------------*/
  1215. #if defined(NeXT) && (NS_TARGET_MAJOR < 4)/* NeXTSTEP rld functions */
  1216. {
  1217. NXStream* s;
  1218. unsigned long init_address;
  1219. char *object_files[2] = {NULL, NULL};
  1220. void (*init_fct)();
  1221. object_files[0] = (char*)file;
  1222. s = NXOpenFile(2,NX_WRITEONLY);
  1223. /* Load object file, if return value ==0 , load failed*/
  1224. if(rld_load(s, NULL, object_files, NULL) == 0) {
  1225. NXFlush(s);
  1226. NXClose(s);
  1227. dln_loaderror("Failed to load %.200s", file);
  1228. }
  1229. /* lookup the initial function */
  1230. if(rld_lookup(s, buf, &init_address) == 0) {
  1231. NXFlush(s);
  1232. NXClose(s);
  1233. dln_loaderror("Failed to lookup Init function %.200s", file);
  1234. }
  1235. NXFlush(s);
  1236. NXClose(s);
  1237. /* Cannot call *init_address directory, so copy this value to
  1238. function pointer */
  1239. init_fct = (void(*)())init_address;
  1240. (*init_fct)();
  1241. return (void*)init_address;
  1242. }
  1243. #else/* OPENSTEP dyld functions */
  1244. {
  1245. int dyld_result;
  1246. NSObjectFileImage obj_file; /* handle, but not use it */
  1247. /* "file" is module file name .
  1248. "buf" is pointer to initial function name with "_" . */
  1249. void (*init_fct)();
  1250. dyld_result = NSCreateObjectFileImageFromFile(file, &obj_file);
  1251. if (dyld_result != NSObjectFileImageSuccess) {
  1252. dln_loaderror("Failed to load %.200s", file);
  1253. }
  1254. NSLinkModule(obj_file, file, NSLINKMODULE_OPTION_BINDNOW);
  1255. /* lookup the initial function */
  1256. if(!NSIsSymbolNameDefined(buf)) {
  1257. dln_loaderror("Failed to lookup Init function %.200s",file);
  1258. }
  1259. init_fct = NSAddressOfSymbol(NSLookupAndBindSymbol(buf));
  1260. (*init_fct)();
  1261. return (void*)init_fct;
  1262. }
  1263. #endif /* rld or dyld */
  1264. #endif
  1265. #if defined(__BEOS__) || defined(__HAIKU__)
  1266. # define DLN_DEFINED
  1267. {
  1268. status_t err_stat; /* BeOS error status code */
  1269. image_id img_id; /* extension module unique id */
  1270. void (*init_fct)(); /* initialize function for extension module */
  1271. /* load extension module */
  1272. img_id = load_add_on(file);
  1273. if (img_id <= 0) {
  1274. dln_loaderror("Failed to load add_on %.200s error_code=%x",
  1275. file, img_id);
  1276. }
  1277. /* find symbol for module initialize function. */
  1278. /* The Be Book KernelKit Images section described to use
  1279. B_SYMBOL_TYPE_TEXT for symbol of function, not
  1280. B_SYMBOL_TYPE_CODE. Why ? */
  1281. /* strcat(init_fct_symname, "__Fv"); */ /* parameter nothing. */
  1282. /* "__Fv" dont need! The Be Book Bug ? */
  1283. err_stat = get_image_symbol(img_id, buf,
  1284. B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
  1285. if (err_stat != B_NO_ERROR) {
  1286. char real_name[MAXPATHLEN];
  1287. strlcpy(real_name, buf, MAXPATHLEN);
  1288. strlcat(real_name, "__Fv", MAXPATHLEN);
  1289. err_stat = get_image_symbol(img_id, real_name,
  1290. B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
  1291. }
  1292. if ((B_BAD_IMAGE_ID == err_stat) || (B_BAD_INDEX == err_stat)) {
  1293. unload_add_on(img_id);
  1294. dln_loaderror("Failed to lookup Init function %.200s", file);
  1295. }
  1296. else if (B_NO_ERROR != err_stat) {
  1297. char errmsg[] = "Internal of BeOS version. %.200s (symbol_name = %s)";
  1298. unload_add_on(img_id);
  1299. dln_loaderror(errmsg, strerror(err_stat), buf);
  1300. }
  1301. /* call module initialize function. */
  1302. (*init_fct)();
  1303. return (void*)img_id;
  1304. }
  1305. #endif /* __BEOS__ || __HAIKU__ */
  1306. #ifndef DLN_DEFINED
  1307. dln_notimplement();
  1308. #endif
  1309. #endif /* USE_DLN_A_OUT */
  1310. #endif
  1311. #if !defined(_AIX) && !defined(NeXT)
  1312. failed:
  1313. dln_loaderror("%s - %s", error, file);
  1314. #endif
  1315. return 0; /* dummy return */
  1316. }