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