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