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