Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

handle.c
Go to the documentation of this file.
1 /* -*- C -*-
2 * $Id: handle.c 35321 2012-04-13 23:45:37Z drbrain $
3 */
4
5 #include <ruby.h>
6 #include "dl.h"
7
8 VALUE rb_cDLHandle;
9
10 #ifdef _WIN32
11 # ifndef _WIN32_WCE
12 static void *
13 w32_coredll(void)
14 {
15 MEMORY_BASIC_INFORMATION m;
16 memset(&m, 0, sizeof(m));
17 if( !VirtualQuery(_errno, &m, sizeof(m)) ) return NULL;
18 return m.AllocationBase;
19 }
20 # endif
21
22 static int
23 w32_dlclose(void *ptr)
24 {
25 # ifndef _WIN32_WCE
26 if( ptr == w32_coredll() ) return 0;
27 # endif
28 if( FreeLibrary((HMODULE)ptr) ) return 0;
29 return errno = rb_w32_map_errno(GetLastError());
30 }
31 #define dlclose(ptr) w32_dlclose(ptr)
32 #endif
33
34 static void
35 dlhandle_free(void *ptr)
36 {
37 struct dl_handle *dlhandle = ptr;
38 if( dlhandle->ptr && dlhandle->open && dlhandle->enable_close ){
39 dlclose(dlhandle->ptr);
40 }
41 }
42
43 static size_t
44 dlhandle_memsize(const void *ptr)
45 {
46 return ptr ? sizeof(struct dl_handle) : 0;
47 }
48
49 static const rb_data_type_t dlhandle_data_type = {
50 "dl/handle",
51 {0, dlhandle_free, dlhandle_memsize,},
52 };
53
54 /*
55 * call-seq: close
56 *
57 * Close this DL::Handle. Calling close more than once will raise a
58 * DL::DLError exception.
59 */
60 VALUE
61 rb_dlhandle_close(VALUE self)
62 {
63 struct dl_handle *dlhandle;
64
65 TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
66 if(dlhandle->open) {
67 int ret = dlclose(dlhandle->ptr);
68 dlhandle->open = 0;
69
70 /* Check dlclose for successful return value */
71 if(ret) {
72 #if defined(HAVE_DLERROR)
73 rb_raise(rb_eDLError, "%s", dlerror());
74 #else
75 rb_raise(rb_eDLError, "could not close handle");
76 #endif
77 }
78 return INT2NUM(ret);
79 }
80 rb_raise(rb_eDLError, "dlclose() called too many times");
81
82 UNREACHABLE;
83 }
84
85 VALUE
86 rb_dlhandle_s_allocate(VALUE klass)
87 {
88 VALUE obj;
89 struct dl_handle *dlhandle;
90
91 obj = TypedData_Make_Struct(rb_cDLHandle, struct dl_handle, &dlhandle_data_type, dlhandle);
92 dlhandle->ptr = 0;
93 dlhandle->open = 0;
94 dlhandle->enable_close = 0;
95
96 return obj;
97 }
98
99 static VALUE
100 predefined_dlhandle(void *handle)
101 {
102 VALUE obj = rb_dlhandle_s_allocate(rb_cDLHandle);
103 struct dl_handle *dlhandle = DATA_PTR(obj);
104
105 dlhandle->ptr = handle;
106 dlhandle->open = 1;
107 OBJ_FREEZE(obj);
108 return obj;
109 }
110
111 /*
112 * call-seq:
113 * initialize(lib = nil, flags = DL::RTLD_LAZY | DL::RTLD_GLOBAL)
114 *
115 * Create a new handler that opens library named +lib+ with +flags+. If no
116 * library is specified, RTLD_DEFAULT is used.
117 */
118 VALUE
119 rb_dlhandle_initialize(int argc, VALUE argv[], VALUE self)
120 {
121 void *ptr;
122 struct dl_handle *dlhandle;
123 VALUE lib, flag;
124 char *clib;
125 int cflag;
126 const char *err;
127
128 switch( rb_scan_args(argc, argv, "02", &lib, &flag) ){
129 case 0:
130 clib = NULL;
131 cflag = RTLD_LAZY | RTLD_GLOBAL;
132 break;
133 case 1:
134 clib = NIL_P(lib) ? NULL : StringValuePtr(lib);
135 cflag = RTLD_LAZY | RTLD_GLOBAL;
136 break;
137 case 2:
138 clib = NIL_P(lib) ? NULL : StringValuePtr(lib);
139 cflag = NUM2INT(flag);
140 break;
141 default:
142 rb_bug("rb_dlhandle_new");
143 }
144
145 rb_secure(2);
146
147 #if defined(_WIN32)
148 if( !clib ){
149 HANDLE rb_libruby_handle(void);
150 ptr = rb_libruby_handle();
151 }
152 else if( STRCASECMP(clib, "libc") == 0
153 # ifdef RUBY_COREDLL
154 || STRCASECMP(clib, RUBY_COREDLL) == 0
155 || STRCASECMP(clib, RUBY_COREDLL".dll") == 0
156 # endif
157 ){
158 # ifdef _WIN32_WCE
159 ptr = dlopen("coredll.dll", cflag);
160 # else
161 ptr = w32_coredll();
162 # endif
163 }
164 else
165 #endif
166 ptr = dlopen(clib, cflag);
167 #if defined(HAVE_DLERROR)
168 if( !ptr && (err = dlerror()) ){
169 rb_raise(rb_eDLError, "%s", err);
170 }
171 #else
172 if( !ptr ){
173 err = dlerror();
174 rb_raise(rb_eDLError, "%s", err);
175 }
176 #endif
177 TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
178 if( dlhandle->ptr && dlhandle->open && dlhandle->enable_close ){
179 dlclose(dlhandle->ptr);
180 }
181 dlhandle->ptr = ptr;
182 dlhandle->open = 1;
183 dlhandle->enable_close = 0;
184
185 if( rb_block_given_p() ){
186 rb_ensure(rb_yield, self, rb_dlhandle_close, self);
187 }
188
189 return Qnil;
190 }
191
192 /*
193 * call-seq: enable_close
194 *
195 * Enable a call to dlclose() when this DL::Handle is garbage collected.
196 */
197 VALUE
198 rb_dlhandle_enable_close(VALUE self)
199 {
200 struct dl_handle *dlhandle;
201
202 TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
203 dlhandle->enable_close = 1;
204 return Qnil;
205 }
206
207 /*
208 * call-seq: disable_close
209 *
210 * Disable a call to dlclose() when this DL::Handle is garbage collected.
211 */
212 VALUE
213 rb_dlhandle_disable_close(VALUE self)
214 {
215 struct dl_handle *dlhandle;
216
217 TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
218 dlhandle->enable_close = 0;
219 return Qnil;
220 }
221
222 /*
223 * call-seq: close_enabled?
224 *
225 * Returns +true+ if dlclose() will be called when this DL::Handle is
226 * garbage collected.
227 */
228 static VALUE
229 rb_dlhandle_close_enabled_p(VALUE self)
230 {
231 struct dl_handle *dlhandle;
232
233 TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
234
235 if(dlhandle->enable_close) return Qtrue;
236 return Qfalse;
237 }
238
239 /*
240 * call-seq: to_i
241 *
242 * Returns the memory address for this handle.
243 */
244 VALUE
245 rb_dlhandle_to_i(VALUE self)
246 {
247 struct dl_handle *dlhandle;
248
249 TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
250 return PTR2NUM(dlhandle);
251 }
252
253 static VALUE dlhandle_sym(void *handle, const char *symbol);
254
255 /*
256 * Document-method: sym
257 * Document-method: []
258 *
259 * call-seq: sym(name)
260 *
261 * Get the address as an Integer for the function named +name+.
262 */
263 VALUE
264 rb_dlhandle_sym(VALUE self, VALUE sym)
265 {
266 struct dl_handle *dlhandle;
267
268 TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
269 if( ! dlhandle->open ){
270 rb_raise(rb_eDLError, "closed handle");
271 }
272
273 return dlhandle_sym(dlhandle->ptr, StringValueCStr(sym));
274 }
275
276 #ifndef RTLD_NEXT
277 #define RTLD_NEXT NULL
278 #endif
279 #ifndef RTLD_DEFAULT
280 #define RTLD_DEFAULT NULL
281 #endif
282
283 /*
284 * Document-method: sym
285 * Document-method: []
286 *
287 * call-seq: sym(name)
288 *
289 * Get the address as an Integer for the function named +name+. The function
290 * is searched via dlsym on RTLD_NEXT. See man(3) dlsym() for more info.
291 */
292 VALUE
293 rb_dlhandle_s_sym(VALUE self, VALUE sym)
294 {
295 return dlhandle_sym(RTLD_NEXT, StringValueCStr(sym));
296 }
297
298 static VALUE
299 dlhandle_sym(void *handle, const char *name)
300 {
301 #if defined(HAVE_DLERROR)
302 const char *err;
303 # define CHECK_DLERROR if( err = dlerror() ){ func = 0; }
304 #else
305 # define CHECK_DLERROR
306 #endif
307 void (*func)();
308
309 rb_secure(2);
310 #ifdef HAVE_DLERROR
311 dlerror();
312 #endif
313 func = (void (*)())(VALUE)dlsym(handle, name);
314 CHECK_DLERROR;
315 #if defined(FUNC_STDCALL)
316 if( !func ){
317 int i;
318 int len = (int)strlen(name);
319 char *name_n;
320 #if defined(__CYGWIN__) || defined(_WIN32) || defined(__MINGW32__)
321 {
322 char *name_a = (char*)xmalloc(len+2);
323 strcpy(name_a, name);
324 name_n = name_a;
325 name_a[len] = 'A';
326 name_a[len+1] = '\0';
327 func = dlsym(handle, name_a);
328 CHECK_DLERROR;
329 if( func ) goto found;
330 name_n = xrealloc(name_a, len+6);
331 }
332 #else
333 name_n = (char*)xmalloc(len+6);
334 #endif
335 memcpy(name_n, name, len);
336 name_n[len++] = '@';
337 for( i = 0; i < 256; i += 4 ){
338 sprintf(name_n + len, "%d", i);
339 func = dlsym(handle, name_n);
340 CHECK_DLERROR;
341 if( func ) break;
342 }
343 if( func ) goto found;
344 name_n[len-1] = 'A';
345 name_n[len++] = '@';
346 for( i = 0; i < 256; i += 4 ){
347 sprintf(name_n + len, "%d", i);
348 func = dlsym(handle, name_n);
349 CHECK_DLERROR;
350 if( func ) break;
351 }
352 found:
353 xfree(name_n);
354 }
355 #endif
356 if( !func ){
357 rb_raise(rb_eDLError, "unknown symbol \"%s\"", name);
358 }
359
360 return PTR2NUM(func);
361 }
362
363 void
364 Init_dlhandle(void)
365 {
366 /*
367 * Document-class: DL::Handle
368 *
369 * The DL::Handle is the manner to access the dynamic library
370 *
371 * == Example
372 *
373 * === Setup
374 *
375 * libc_so = "/lib64/libc.so.6"
376 * => "/lib64/libc.so.6"
377 * @handle = DL::Handle.new(libc_so)
378 * => #<DL::Handle:0x00000000d69ef8>
379 *
380 * === Setup, with flags
381 *
382 * libc_so = "/lib64/libc.so.6"
383 * => "/lib64/libc.so.6"
384 * @handle = DL::Handle.new(libc_so, DL::RTLD_LAZY | DL::RTLD_GLOBAL)
385 * => #<DL::Handle:0x00000000d69ef8>
386 *
387 * === Addresses to symbols
388 *
389 * strcpy_addr = @handle['strcpy']
390 * => 140062278451968
391 *
392 * or
393 *
394 * strcpy_addr = @handle.sym('strcpy')
395 * => 140062278451968
396 *
397 */
398 rb_cDLHandle = rb_define_class_under(rb_mDL, "Handle", rb_cObject);
399 rb_define_alloc_func(rb_cDLHandle, rb_dlhandle_s_allocate);
400 rb_define_singleton_method(rb_cDLHandle, "sym", rb_dlhandle_s_sym, 1);
401 rb_define_singleton_method(rb_cDLHandle, "[]", rb_dlhandle_s_sym, 1);
402
403 /* Document-const: NEXT
404 *
405 * A predefined pseudo-handle of RTLD_NEXT
406 *
407 * Which will find the next occurrence of a function in the search order
408 * after the current library.
409 */
410 rb_define_const(rb_cDLHandle, "NEXT", predefined_dlhandle(RTLD_NEXT));
411
412 /* Document-const: DEFAULT
413 *
414 * A predefined pseudo-handle of RTLD_DEFAULT
415 *
416 * Which will find the first occurrence of the desired symbol using the
417 * default library search order
418 */
419 rb_define_const(rb_cDLHandle, "DEFAULT", predefined_dlhandle(RTLD_DEFAULT));
420 rb_define_method(rb_cDLHandle, "initialize", rb_dlhandle_initialize, -1);
421 rb_define_method(rb_cDLHandle, "to_i", rb_dlhandle_to_i, 0);
422 rb_define_method(rb_cDLHandle, "close", rb_dlhandle_close, 0);
423 rb_define_method(rb_cDLHandle, "sym", rb_dlhandle_sym, 1);
424 rb_define_method(rb_cDLHandle, "[]", rb_dlhandle_sym, 1);
425 rb_define_method(rb_cDLHandle, "disable_close", rb_dlhandle_disable_close, 0);
426 rb_define_method(rb_cDLHandle, "enable_close", rb_dlhandle_enable_close, 0);
427 rb_define_method(rb_cDLHandle, "close_enabled?", rb_dlhandle_close_enabled_p, 0);
428 }
429
430 /* mode: c; tab-with=8; sw=4; ts=8; noexpandtab: */
dlhandle_memsize
static size_t dlhandle_memsize(const void *ptr)
Definition: handle.c:44
rb_dlhandle_close_enabled_p
static VALUE rb_dlhandle_close_enabled_p(VALUE self)
Definition: handle.c:229
sym
VALUE sym
Definition: tkutil.c:1299
int
VP_EXPORT int
Definition: bigdecimal.c:5050
rb_mDL
VALUE rb_mDL
Definition: dl.c:13
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:290
strlen
size_t strlen(const char *)
dl_handle::open
int open
Definition: dl.h:183
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1497
dl_handle
Definition: dl.h:181
RTLD_DEFAULT
#define RTLD_DEFAULT
Definition: handle.c:280
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:108
rb_secure
void rb_secure(int)
Definition: safe.c:79
i
ssize_t i
Definition: bigdecimal.c:5655
ruby.h
ret
int ret
Definition: tcltklib.c:280
rb_dlhandle_initialize
VALUE rb_dlhandle_initialize(int argc, VALUE argv[], VALUE self)
Definition: handle.c:119
OBJ_FREEZE
#define OBJ_FREEZE(x)
dl.h
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
UNREACHABLE
#define UNREACHABLE
Definition: ruby.h:40
NIL_P
NIL_P(eventloop_thread)
Definition: tcltklib.c:4068
dlhandle_data_type
static const rb_data_type_t dlhandle_data_type
Definition: handle.c:49
xfree
#define xfree
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:545
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
Qtrue
return Qtrue
Definition: tcltklib.c:9610
rb_dlhandle_enable_close
VALUE rb_dlhandle_enable_close(VALUE self)
Definition: handle.c:198
rb_eDLError
VALUE rb_eDLError
Definition: dl.c:14
rb_dlhandle_to_i
VALUE rb_dlhandle_to_i(VALUE self)
Definition: handle.c:245
rb_w32_map_errno
int rb_w32_map_errno(DWORD)
Definition: win32.c:223
flag
flag
Definition: tcltklib.c:2048
RTLD_NEXT
#define RTLD_NEXT
Definition: handle.c:277
strcpy
strcpy(cmd2, cmd)
memset
memset(y->frac+ix+1, 0,(y->Prec-(ix+1))*sizeof(BDIGIT))
m
BDIGIT m
Definition: bigdecimal.c:5085
Qfalse
return Qfalse
Definition: tcltklib.c:6779
TypedData_Get_Struct
#define TypedData_Get_Struct(obj, type, data_type, sval)
rb_block_given_p
int rb_block_given_p(void)
Definition: eval.c:672
Qnil
#define Qnil
Definition: tcltklib.c:1896
StringValuePtr
#define StringValuePtr(v)
STRCASECMP
#define STRCASECMP(s1, s2)
dlhandle_sym
static VALUE dlhandle_sym(void *handle, const char *symbol)
Definition: handle.c:299
StringValueCStr
#define StringValueCStr(v)
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2202
rb_dlhandle_s_allocate
VALUE rb_dlhandle_s_allocate(VALUE klass)
Definition: handle.c:86
obj
static VALUE VALUE obj
Definition: tcltklib.c:3158
dl_handle::enable_close
int enable_close
Definition: dl.h:184
PTR2NUM
#define PTR2NUM(x)
Definition: dl.h:168
Init_dlhandle
void Init_dlhandle(void)
Definition: handle.c:364
xmalloc
#define xmalloc
xrealloc
#define xrealloc
err
int err
Definition: win32.c:87
argv
VALUE * argv
Definition: tcltklib.c:1971
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:934
memcpy
memcpy(buf+1, str, len)
errno
int errno
const
#define const
Definition: strftime.c:102
void
VP_EXPORT void
Definition: bigdecimal.c:5083
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1570
rb_dlhandle_s_sym
VALUE rb_dlhandle_s_sym(VALUE self, VALUE sym)
Definition: handle.c:293
argc
int argc
Definition: tcltklib.c:1970
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:804
ptr
return ptr
Definition: tcltklib.c:784
rb_dlhandle_close
VALUE rb_dlhandle_close(VALUE self)
Definition: handle.c:61
predefined_dlhandle
static VALUE predefined_dlhandle(void *handle)
Definition: handle.c:100
rb_dlhandle_disable_close
VALUE rb_dlhandle_disable_close(VALUE self)
Definition: handle.c:213
rb_data_type_struct
Definition: ripper.y:960
rb_dlhandle_sym
VALUE rb_dlhandle_sym(VALUE self, VALUE sym)
Definition: handle.c:264
DATA_PTR
DATA_PTR(self)
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1426
klass
klass
Definition: tcltklib.c:3504
INT2NUM
#define INT2NUM(x)
dlhandle_free
static void dlhandle_free(void *ptr)
Definition: handle.c:35
NUM2INT
#define NUM2INT(x)
VALUE
unsigned long VALUE
Definition: ripper.y:104
rb_cDLHandle
VALUE rb_cDLHandle
Definition: handle.c:8
CHECK_DLERROR
#define CHECK_DLERROR
dl_handle::ptr
void * ptr
Definition: dl.h:182
NULL
#define NULL
Definition: _sdbm.c:103
name
const char * name
Definition: nkf.c:208
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
len
size_t len
Definition: tcltklib.c:3568