Ruby  2.0.0p648(2015-12-16revision53162)
dl.c
Go to the documentation of this file.
1 /*
2  * ext/dl/dl.c
3  *
4  * doumentation:
5  * - Vincent Batts (vbatts@hashbangbash.com)
6  *
7  */
8 #include <ruby/ruby.h>
9 #include <ruby/io.h>
10 #include <ctype.h>
11 #include "dl.h"
12 
16 
19 
20 #ifndef DLTYPE_SSIZE_T
21 # if SIZEOF_SIZE_T == SIZEOF_INT
22 # define DLTYPE_SSIZE_T DLTYPE_INT
23 # elif SIZEOF_SIZE_T == SIZEOF_LONG
24 # define DLTYPE_SSIZE_T DLTYPE_LONG
25 # elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG
26 # define DLTYPE_SSIZE_T DLTYPE_LONG_LONG
27 # endif
28 #endif
29 #define DLTYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*DLTYPE_SSIZE_T)
30 
31 #ifndef DLTYPE_PTRDIFF_T
32 # if SIZEOF_PTRDIFF_T == SIZEOF_INT
33 # define DLTYPE_PTRDIFF_T DLTYPE_INT
34 # elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
35 # define DLTYPE_PTRDIFF_T DLTYPE_LONG
36 # elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
37 # define DLTYPE_PTRDIFF_T DLTYPE_LONG_LONG
38 # endif
39 #endif
40 
41 #ifndef DLTYPE_INTPTR_T
42 # if SIZEOF_INTPTR_T == SIZEOF_INT
43 # define DLTYPE_INTPTR_T DLTYPE_INT
44 # elif SIZEOF_INTPTR_T == SIZEOF_LONG
45 # define DLTYPE_INTPTR_T DLTYPE_LONG
46 # elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
47 # define DLTYPE_INTPTR_T DLTYPE_LONG_LONG
48 # endif
49 #endif
50 #define DLTYPE_UINTPTR_T (-DLTYPE_INTPTR_T)
51 
52 /*
53  * call-seq: DL.dlopen(so_lib)
54  *
55  * An interface to the dynamic linking loader
56  *
57  * This is a shortcut to DL::Handle.new and takes the same arguments.
58  *
59  * Example:
60  *
61  * libc_so = "/lib64/libc.so.6"
62  * => "/lib64/libc.so.6"
63  *
64  * libc = DL.dlopen(libc_so)
65  * => #<DL::Handle:0x00000000e05b00>
66  */
67 VALUE
69 {
70  return rb_class_new_instance(argc, argv, rb_cDLHandle);
71 }
72 
73 /*
74  * call-seq: DL.malloc(size)
75  *
76  * Allocate +size+ bytes of memory and return the integer memory address
77  * for the allocated memory.
78  */
79 VALUE
81 {
82  void *ptr;
83 
84  rb_secure(4);
85  ptr = (void*)ruby_xmalloc(NUM2INT(size));
86  return PTR2NUM(ptr);
87 }
88 
89 /*
90  * call-seq: DL.realloc(addr, size)
91  *
92  * Change the size of the memory allocated at the memory location +addr+ to
93  * +size+ bytes. Returns the memory address of the reallocated memory, which
94  * may be different than the address passed in.
95  */
96 VALUE
98 {
99  void *ptr = NUM2PTR(addr);
100 
101  rb_secure(4);
102  ptr = (void*)ruby_xrealloc(ptr, NUM2INT(size));
103  return PTR2NUM(ptr);
104 }
105 
106 /*
107  * call-seq: DL.free(addr)
108  *
109  * Free the memory at address +addr+
110  */
111 VALUE
112 rb_dl_free(VALUE self, VALUE addr)
113 {
114  void *ptr = NUM2PTR(addr);
115 
116  rb_secure(4);
117  ruby_xfree(ptr);
118  return Qnil;
119 }
120 
121 /*
122  * call-seq: DL.dlunwrap(addr)
123  *
124  * Returns the hexadecimal representation of a memory pointer address +addr+
125  *
126  * Example:
127  *
128  * lib = DL.dlopen('/lib64/libc-2.15.so')
129  * => #<DL::Handle:0x00000001342460>
130  *
131  * lib['strcpy'].to_s(16)
132  * => "7f59de6dd240"
133  *
134  * DL.dlunwrap(DL.dlwrap(lib['strcpy'].to_s(16)))
135  * => "7f59de6dd240"
136  */
137 VALUE
139 {
140  rb_secure(4);
141  return (VALUE)NUM2PTR(addr);
142 }
143 
144 /*
145  * call-seq: DL.dlwrap(val)
146  *
147  * Returns a memory pointer of a function's hexadecimal address location +val+
148  *
149  * Example:
150  *
151  * lib = DL.dlopen('/lib64/libc-2.15.so')
152  * => #<DL::Handle:0x00000001342460>
153  *
154  * DL.dlwrap(lib['strcpy'].to_s(16))
155  * => 25522520
156  */
157 VALUE
159 {
160  return PTR2NUM((void*)val);
161 }
162 
163 static void
165 {
166  static const char cb[] = "dl/callback.so";
167 
168  rb_autoload(dl, rb_intern_const("CdeclCallbackAddrs"), cb);
169  rb_autoload(dl, rb_intern_const("CdeclCallbackProcs"), cb);
170 #ifdef FUNC_STDCALL
171  rb_autoload(dl, rb_intern_const("StdcallCallbackAddrs"), cb);
172  rb_autoload(dl, rb_intern_const("StdcallCallbackProcs"), cb);
173 #endif
174 }
175 
176 void
177 Init_dl(void)
178 {
179  void Init_dlhandle(void);
180  void Init_dlcfunc(void);
181  void Init_dlptr(void);
182 
183  rbdl_id_cdecl = rb_intern_const("cdecl");
184  rbdl_id_stdcall = rb_intern_const("stdcall");
185 
186  /* Document-module: DL
187  *
188  * A bridge to the dlopen() or dynamic library linker function.
189  *
190  * == Example
191  *
192  * bash $> cat > sum.c <<EOF
193  * double sum(double *arry, int len)
194  * {
195  * double ret = 0;
196  * int i;
197  * for(i = 0; i < len; i++){
198  * ret = ret + arry[i];
199  * }
200  * return ret;
201  * }
202  *
203  * double split(double num)
204  * {
205  * double ret = 0;
206  * ret = num / 2;
207  * return ret;
208  * }
209  * EOF
210  * bash $> gcc -o libsum.so -shared sum.c
211  * bash $> cat > sum.rb <<EOF
212  * require 'dl'
213  * require 'dl/import'
214  *
215  * module LibSum
216  * extend DL::Importer
217  * dlload './libsum.so'
218  * extern 'double sum(double*, int)'
219  * extern 'double split(double)'
220  * end
221  *
222  * a = [2.0, 3.0, 4.0]
223  *
224  * sum = LibSum.sum(a.pack("d*"), a.count)
225  * p LibSum.split(sum)
226  * EOF
227  * bash $> ruby sum.rb
228  * 4.5
229  *
230  * WIN! :-)
231  */
232  rb_mDL = rb_define_module("DL");
233 
234  /*
235  * Document-class: DL::DLError
236  *
237  * standard dynamic load exception
238  */
240 
241  /*
242  * Document-class: DL::DLTypeError
243  *
244  * dynamic load incorrect type exception
245  */
247 
248  /* Document-const: MAX_CALLBACK
249  *
250  * Maximum number of callbacks
251  */
252  rb_define_const(rb_mDL, "MAX_CALLBACK", INT2NUM(MAX_CALLBACK));
253 
254  /* Document-const: DLSTACK_SIZE
255  *
256  * Dynamic linker stack size
257  */
258  rb_define_const(rb_mDL, "DLSTACK_SIZE", INT2NUM(DLSTACK_SIZE));
259 
261 
262  /* Document-const: RTLD_GLOBAL
263  *
264  * rtld DL::Handle flag.
265  *
266  * The symbols defined by this library will be made available for symbol
267  * resolution of subsequently loaded libraries.
268  */
269  rb_define_const(rb_mDL, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL));
270 
271  /* Document-const: RTLD_LAZY
272  *
273  * rtld DL::Handle flag.
274  *
275  * Perform lazy binding. Only resolve symbols as the code that references
276  * them is executed. If the symbol is never referenced, then it is never
277  * resolved. (Lazy binding is only performed for function references;
278  * references to variables are always immediately bound when the library
279  * is loaded.)
280  */
281  rb_define_const(rb_mDL, "RTLD_LAZY", INT2NUM(RTLD_LAZY));
282 
283  /* Document-const: RTLD_NOW
284  *
285  * rtld DL::Handle flag.
286  *
287  * If this value is specified or the environment variable LD_BIND_NOW is
288  * set to a nonempty string, all undefined symbols in the library are
289  * resolved before dlopen() returns. If this cannot be done an error is
290  * returned.
291  */
292  rb_define_const(rb_mDL, "RTLD_NOW", INT2NUM(RTLD_NOW));
293 
294  /* Document-const: TYPE_VOID
295  *
296  * DL::CFunc type - void
297  */
298  rb_define_const(rb_mDL, "TYPE_VOID", INT2NUM(DLTYPE_VOID));
299 
300  /* Document-const: TYPE_VOIDP
301  *
302  * DL::CFunc type - void*
303  */
304  rb_define_const(rb_mDL, "TYPE_VOIDP", INT2NUM(DLTYPE_VOIDP));
305 
306  /* Document-const: TYPE_CHAR
307  *
308  * DL::CFunc type - char
309  */
310  rb_define_const(rb_mDL, "TYPE_CHAR", INT2NUM(DLTYPE_CHAR));
311 
312  /* Document-const: TYPE_SHORT
313  *
314  * DL::CFunc type - short
315  */
316  rb_define_const(rb_mDL, "TYPE_SHORT", INT2NUM(DLTYPE_SHORT));
317 
318  /* Document-const: TYPE_INT
319  *
320  * DL::CFunc type - int
321  */
322  rb_define_const(rb_mDL, "TYPE_INT", INT2NUM(DLTYPE_INT));
323 
324  /* Document-const: TYPE_LONG
325  *
326  * DL::CFunc type - long
327  */
328  rb_define_const(rb_mDL, "TYPE_LONG", INT2NUM(DLTYPE_LONG));
329 
330 #if HAVE_LONG_LONG
331  /* Document-const: TYPE_LONG_LONG
332  *
333  * DL::CFunc type - long long
334  */
335  rb_define_const(rb_mDL, "TYPE_LONG_LONG", INT2NUM(DLTYPE_LONG_LONG));
336 #endif
337 
338  /* Document-const: TYPE_FLOAT
339  *
340  * DL::CFunc type - float
341  */
342  rb_define_const(rb_mDL, "TYPE_FLOAT", INT2NUM(DLTYPE_FLOAT));
343 
344  /* Document-const: TYPE_DOUBLE
345  *
346  * DL::CFunc type - double
347  */
348  rb_define_const(rb_mDL, "TYPE_DOUBLE", INT2NUM(DLTYPE_DOUBLE));
349 
350  /* Document-const: TYPE_SIZE_T
351  *
352  * DL::CFunc type - size_t
353  */
354  rb_define_const(rb_mDL, "TYPE_SIZE_T", INT2NUM(DLTYPE_SIZE_T));
355 
356  /* Document-const: TYPE_SSIZE_T
357  *
358  * DL::CFunc type - ssize_t
359  */
360  rb_define_const(rb_mDL, "TYPE_SSIZE_T", INT2NUM(DLTYPE_SSIZE_T));
361 
362  /* Document-const: TYPE_PTRDIFF_T
363  *
364  * DL::CFunc type - ptrdiff_t
365  */
366  rb_define_const(rb_mDL, "TYPE_PTRDIFF_T", INT2NUM(DLTYPE_PTRDIFF_T));
367 
368  /* Document-const: TYPE_INTPTR_T
369  *
370  * DL::CFunc type - intptr_t
371  */
372  rb_define_const(rb_mDL, "TYPE_INTPTR_T", INT2NUM(DLTYPE_INTPTR_T));
373 
374  /* Document-const: TYPE_UINTPTR_T
375  *
376  * DL::CFunc type - uintptr_t
377  */
378  rb_define_const(rb_mDL, "TYPE_UINTPTR_T", INT2NUM(DLTYPE_UINTPTR_T));
379 
380  /* Document-const: ALIGN_VOIDP
381  *
382  * The alignment size of a void*
383  */
384  rb_define_const(rb_mDL, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP));
385 
386  /* Document-const: ALIGN_CHAR
387  *
388  * The alignment size of a char
389  */
390  rb_define_const(rb_mDL, "ALIGN_CHAR", INT2NUM(ALIGN_CHAR));
391 
392  /* Document-const: ALIGN_SHORT
393  *
394  * The alignment size of a short
395  */
396  rb_define_const(rb_mDL, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT));
397 
398  /* Document-const: ALIGN_INT
399  *
400  * The alignment size of an int
401  */
402  rb_define_const(rb_mDL, "ALIGN_INT", INT2NUM(ALIGN_INT));
403 
404  /* Document-const: ALIGN_LONG
405  *
406  * The alignment size of a long
407  */
408  rb_define_const(rb_mDL, "ALIGN_LONG", INT2NUM(ALIGN_LONG));
409 
410 #if HAVE_LONG_LONG
411  /* Document-const: ALIGN_LONG_LONG
412  *
413  * The alignment size of a long long
414  */
415  rb_define_const(rb_mDL, "ALIGN_LONG_LONG", INT2NUM(ALIGN_LONG_LONG));
416 #endif
417 
418  /* Document-const: ALIGN_FLOAT
419  *
420  * The alignment size of a float
421  */
422  rb_define_const(rb_mDL, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT));
423 
424  /* Document-const: ALIGN_DOUBLE
425  *
426  * The alignment size of a double
427  */
428  rb_define_const(rb_mDL, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE));
429 
430  /* Document-const: ALIGN_SIZE_T
431  *
432  * The alignment size of a size_t
433  */
434  rb_define_const(rb_mDL, "ALIGN_SIZE_T", INT2NUM(ALIGN_OF(size_t)));
435 
436  /* Document-const: ALIGN_SSIZE_T
437  *
438  * The alignment size of a ssize_t
439  */
440  rb_define_const(rb_mDL, "ALIGN_SSIZE_T", INT2NUM(ALIGN_OF(size_t))); /* same as size_t */
441 
442  /* Document-const: ALIGN_PTRDIFF_T
443  *
444  * The alignment size of a ptrdiff_t
445  */
446  rb_define_const(rb_mDL, "ALIGN_PTRDIFF_T", INT2NUM(ALIGN_OF(ptrdiff_t)));
447 
448  /* Document-const: ALIGN_INTPTR_T
449  *
450  * The alignment size of a intptr_t
451  */
452  rb_define_const(rb_mDL, "ALIGN_INTPTR_T", INT2NUM(ALIGN_OF(intptr_t)));
453 
454  /* Document-const: ALIGN_UINTPTR_T
455  *
456  * The alignment size of a uintptr_t
457  */
458  rb_define_const(rb_mDL, "ALIGN_UINTPTR_T", INT2NUM(ALIGN_OF(uintptr_t)));
459 
460  /* Document-const: SIZEOF_VOIDP
461  *
462  * size of a void*
463  */
464  rb_define_const(rb_mDL, "SIZEOF_VOIDP", INT2NUM(sizeof(void*)));
465 
466  /* Document-const: SIZEOF_CHAR
467  *
468  * size of a char
469  */
470  rb_define_const(rb_mDL, "SIZEOF_CHAR", INT2NUM(sizeof(char)));
471 
472  /* Document-const: SIZEOF_SHORT
473  *
474  * size of a short
475  */
476  rb_define_const(rb_mDL, "SIZEOF_SHORT", INT2NUM(sizeof(short)));
477 
478  /* Document-const: SIZEOF_INT
479  *
480  * size of an int
481  */
482  rb_define_const(rb_mDL, "SIZEOF_INT", INT2NUM(sizeof(int)));
483 
484  /* Document-const: SIZEOF_LONG
485  *
486  * size of a long
487  */
488  rb_define_const(rb_mDL, "SIZEOF_LONG", INT2NUM(sizeof(long)));
489 
490 #if HAVE_LONG_LONG
491  /* Document-const: SIZEOF_LONG_LONG
492  *
493  * size of a long long
494  */
495  rb_define_const(rb_mDL, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG)));
496 #endif
497 
498  /* Document-const: SIZEOF_FLOAT
499  *
500  * size of a float
501  */
502  rb_define_const(rb_mDL, "SIZEOF_FLOAT", INT2NUM(sizeof(float)));
503 
504  /* Document-const: SIZEOF_DOUBLE
505  *
506  * size of a double
507  */
508  rb_define_const(rb_mDL, "SIZEOF_DOUBLE",INT2NUM(sizeof(double)));
509 
510  /* Document-const: SIZEOF_SIZE_T
511  *
512  * size of a size_t
513  */
514  rb_define_const(rb_mDL, "SIZEOF_SIZE_T", INT2NUM(sizeof(size_t)));
515 
516  /* Document-const: SIZEOF_SSIZE_T
517  *
518  * size of a ssize_t
519  */
520  rb_define_const(rb_mDL, "SIZEOF_SSIZE_T", INT2NUM(sizeof(size_t))); /* same as size_t */
521 
522  /* Document-const: SIZEOF_PTRDIFF_T
523  *
524  * size of a ptrdiff_t
525  */
526  rb_define_const(rb_mDL, "SIZEOF_PTRDIFF_T", INT2NUM(sizeof(ptrdiff_t)));
527 
528  /* Document-const: SIZEOF_INTPTR_T
529  *
530  * size of a intptr_t
531  */
532  rb_define_const(rb_mDL, "SIZEOF_INTPTR_T", INT2NUM(sizeof(intptr_t)));
533 
534  /* Document-const: SIZEOF_UINTPTR_T
535  *
536  * size of a uintptr_t
537  */
538  rb_define_const(rb_mDL, "SIZEOF_UINTPTR_T", INT2NUM(sizeof(uintptr_t)));
539 
542 
547 
548  /* Document-const: RUBY_FREE
549  *
550  * Address of the ruby_xfree() function
551  */
552  rb_define_const(rb_mDL, "RUBY_FREE", PTR2NUM(ruby_xfree));
553 
554  /* Document-const: BUILD_RUBY_PLATFORM
555  *
556  * Platform built against (i.e. "x86_64-linux", etc.)
557  *
558  * See also RUBY_PLATFORM
559  */
560  rb_define_const(rb_mDL, "BUILD_RUBY_PLATFORM", rb_str_new2(RUBY_PLATFORM));
561 
562  /* Document-const: BUILD_RUBY_VERSION
563  *
564  * Ruby Version built. (i.e. "1.9.3")
565  *
566  * See also RUBY_VERSION
567  */
568  rb_define_const(rb_mDL, "BUILD_RUBY_VERSION", rb_str_new2(RUBY_VERSION));
569 
570  Init_dlhandle();
571  Init_dlcfunc();
572  Init_dlptr();
573 }
ID rbdl_id_stdcall
Definition: dl.c:18
VALUE rb_eStandardError
Definition: error.c:514
VALUE rb_mDL
Definition: dl.c:13
#define INT2NUM(x)
Definition: ruby.h:1178
#define NUM2INT(x)
Definition: ruby.h:622
#define DLTYPE_SHORT
Definition: dl.h:157
static void rb_dl_init_callbacks(VALUE dl)
Definition: dl.c:164
ID rbdl_id_cdecl
Definition: dl.c:17
void rb_autoload(VALUE, ID, const char *)
Definition: variable.c:1604
#define RUBY_VERSION
Definition: tcltklib.c:16
#define NUM2PTR(x)
Definition: dl.h:169
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:534
VALUE rb_dl_realloc(VALUE self, VALUE addr, VALUE size)
Definition: dl.c:97
#define ALIGN_FLOAT
Definition: dl.h:147
VALUE rb_eDLError
Definition: dl.c:14
#define DLTYPE_VOID
Definition: dl.h:154
void * ptr
Definition: dl.h:201
VALUE rb_eDLTypeError
Definition: dl.c:15
#define DLTYPE_INTPTR_T
Definition: dl.c:43
VALUE rb_dl_ptr2value(VALUE self, VALUE addr)
Definition: dl.c:138
#define ALIGN_OF(type)
Definition: dl.h:137
#define ALIGN_VOIDP
Definition: dl.h:139
void Init_dl(void)
Definition: dl.c:177
#define DLTYPE_SIZE_T
Definition: dl.c:29
#define MAX_CALLBACK
Definition: dl.h:34
VALUE rb_class_new_instance(int, VALUE *, VALUE)
Definition: object.c:1794
#define DLTYPE_DOUBLE
Definition: dl.h:164
#define val
VALUE rb_dl_malloc(VALUE self, VALUE size)
Definition: dl.c:80
#define ALIGN_LONG
Definition: dl.h:143
#define PTR2NUM(x)
Definition: dl.h:168
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2204
void Init_dlhandle(void)
Definition: handle.c:370
int argc
Definition: ruby.c:130
#define ALIGN_CHAR
Definition: dl.h:141
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
Definition: class.c:1512
VALUE rb_dl_free(VALUE self, VALUE addr)
Definition: dl.c:112
void ruby_xfree(void *x)
Definition: gc.c:3653
#define DLTYPE_PTRDIFF_T
Definition: dl.c:33
#define ALIGN_SHORT
Definition: dl.h:140
unsigned long ID
Definition: ruby.h:105
#define Qnil
Definition: ruby.h:435
unsigned int uintptr_t
Definition: win32.h:94
unsigned long VALUE
Definition: ruby.h:104
int intptr_t
Definition: win32.h:86
VALUE rb_dl_value2ptr(VALUE self, VALUE val)
Definition: dl.c:158
void * ruby_xmalloc(size_t size)
Definition: gc.c:3596
#define ALIGN_DOUBLE
Definition: dl.h:148
void * ruby_xrealloc(void *ptr, size_t size)
Definition: gc.c:3637
#define RUBY_PLATFORM
Definition: defines.h:237
int size
Definition: encoding.c:52
#define DLTYPE_INT
Definition: dl.h:158
#define DLTYPE_SSIZE_T
Definition: dl.c:22
#define DLTYPE_FLOAT
Definition: dl.h:163
#define DLTYPE_VOIDP
Definition: dl.h:155
void Init_dlptr(void)
Definition: cptr.c:629
#define DLTYPE_LONG
Definition: dl.h:159
#define DLTYPE_CHAR
Definition: dl.h:156
VALUE rb_cDLHandle
Definition: handle.c:10
void rb_secure(int)
Definition: safe.c:79
#define DLTYPE_UINTPTR_T
Definition: dl.c:50
#define rb_intern_const(str)
Definition: ruby.h:1332
VALUE rb_define_module(const char *name)
Definition: class.c:606
VALUE rb_dl_dlopen(int argc, VALUE argv[], VALUE self)
Definition: dl.c:68
#define ALIGN_INT
Definition: dl.h:142
void Init_dlcfunc(void)
Definition: cfunc.c:622
VALUE rb_str_new2(const char *)
#define DLSTACK_SIZE
Definition: dl.h:36
char ** argv
Definition: ruby.c:131