Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libdll/dlfcn.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1997-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* provide dlopen/dlsym/dlerror interface
23
*
24
* David Korn
25
* Glenn Fowler
26
* AT&T Research
27
*/
28
29
static const char id[] = "\n@(#)$Id: dll library (AT&T Research) 2010-10-20 $\0\n";
30
31
#include <ast.h>
32
#include <dlldefs.h>
33
#include <error.h>
34
35
#define T(x) ERROR_dictionary(x)
36
37
#if _BLD_dll && defined(__EXPORT__)
38
#define extern __EXPORT__
39
#endif
40
41
#if _hdr_dlfcn && _lib_dlopen
42
43
/*
44
* standard
45
*/
46
47
# include <dlfcn.h>
48
49
#else
50
#if _hdr_dl
51
52
/*
53
* HP-UX
54
*/
55
56
# include <dl.h>
57
# ifndef BIND_FIRST
58
# define BIND_FIRST 0x4
59
# endif
60
# ifndef BIND_NOSTART
61
# define BIND_NOSTART 0x10
62
# endif
63
64
static shl_t all;
65
static int err;
66
67
extern void* dlopen(const char* path, int mode)
68
{
69
void* dll;
70
71
if (!path)
72
return (void*)&all;
73
if (mode)
74
mode = (BIND_IMMEDIATE|BIND_FIRST|BIND_NOSTART);
75
if (!(dll = (void*)shl_load(path, mode, 0L)))
76
err = errno;
77
return dll;
78
}
79
80
extern int dlclose(void* dll)
81
{
82
return 0;
83
}
84
85
extern void* dlsym(void* dll, const char* name)
86
{
87
shl_t handle;
88
long addr;
89
90
handle = dll == (void*)&all ? (shl_t)0 : (shl_t)dll;
91
if (shl_findsym(&handle, name, TYPE_UNDEFINED, &addr))
92
{
93
err = errno;
94
return 0;
95
}
96
return (void*)addr;
97
}
98
99
extern char* dlerror(void)
100
{
101
char* msg;
102
103
if (!err)
104
return 0;
105
msg = fmterror(err);
106
err = 0;
107
return msg;
108
}
109
110
#else
111
#if _sys_ldr && _lib_loadbind
112
113
/*
114
* rs6000
115
*/
116
117
# include <sys/ldr.h>
118
# include <xcoff.h>
119
120
/* xcoff module header */
121
struct hdr
122
{
123
struct filehdr f;
124
struct aouthdr a;
125
struct scnhdr s[1];
126
};
127
128
static struct ld_info* ld_info;
129
static unsigned int ld_info_size = 1024;
130
static void* last_module;
131
static int err;
132
133
extern void* dlopen(const char* path, int mode)
134
{
135
void* dll;
136
137
if (!(dll = (void*)load((char*)path, mode, getenv("LIBPATH"))))
138
err = errno;
139
return dll;
140
}
141
142
extern int dlclose(void* dll)
143
{
144
return 0;
145
}
146
147
static int getquery(void)
148
{
149
if (!ld_info)
150
ld_info = malloc(ld_info_size);
151
for (;;)
152
{
153
if (!ld_info)
154
return 1;
155
if (!loadquery(L_GETINFO, ld_info, ld_info_size))
156
return 0;
157
if (errno != ENOMEM)
158
return 1;
159
ld_info = realloc(ld_info, ld_info_size *= 2);
160
}
161
}
162
163
/* find the loaded module whose data area contains the
164
* address passed in. Remember that procedure pointers
165
* are implemented as pointers to descriptors in the
166
* data area of the module defining the procedure
167
*/
168
static struct ld_info* getinfo(void* module)
169
{
170
struct ld_info* info = ld_info;
171
register int n = 1;
172
173
if (!ld_info || module != last_module)
174
{
175
last_module = module;
176
if (getquery())
177
return 0;
178
info = ld_info;
179
}
180
while (n)
181
{
182
if ((char*)(info->ldinfo_dataorg) <= (char*)module &&
183
(char*)module <= ((char*)(info->ldinfo_dataorg)
184
+ (unsigned)(info->ldinfo_datasize)))
185
return info;
186
if (n=info->ldinfo_next)
187
info = (void*)((char*)info + n);
188
}
189
return 0;
190
}
191
192
static char* getloc(struct hdr* hdr, char* data, char* name)
193
{
194
struct ldhdr* ldhdr;
195
struct ldsym* ldsym;
196
ulong datareloc;
197
ulong textreloc;
198
int i;
199
200
/* data is relocated by the difference between
201
* its virtual origin and where it was
202
* actually placed
203
*/
204
/*N.B. o_sndata etc. are one based */
205
datareloc = (ulong)data - hdr->s[hdr->a.o_sndata-1].s_vaddr;
206
/*hdr is address of header, not text, so add text s_scnptr */
207
textreloc = (ulong)hdr + hdr->s[hdr->a.o_sntext-1].s_scnptr
208
- hdr->s[hdr->a.o_sntext-1].s_vaddr;
209
ldhdr = (void*)((char*)hdr+ hdr->s[hdr->a.o_snloader-1].s_scnptr);
210
ldsym = (void*) (ldhdr+1);
211
/* search the exports symbols */
212
for(i=0; i < ldhdr->l_nsyms;ldsym++,i++)
213
{
214
char *symname,symbuf[9];
215
char *loc;
216
/* the symbol name representation is a nuisance since
217
* 8 character names appear in l_name but may
218
* not be null terminated. This code works around
219
* that by brute force
220
*/
221
if (ldsym->l_zeroes)
222
{
223
symname = symbuf;
224
memcpy(symbuf,ldsym->l_name,8);
225
symbuf[8] = 0;
226
}
227
else
228
symname = (void*)(ldsym->l_offset + (ulong)ldhdr + ldhdr->l_stoff);
229
if (strcmp(symname,name))
230
continue;
231
loc = (char*)ldsym->l_value;
232
if ((ldsym->l_scnum==hdr->a.o_sndata) ||
233
(ldsym->l_scnum==hdr->a.o_snbss))
234
loc += datareloc;
235
else if (ldsym->l_scnum==hdr->a.o_sntext)
236
loc += textreloc;
237
return loc;
238
}
239
return 0;
240
}
241
242
extern void* dlsym(void* handle, const char* name)
243
{
244
void* addr;
245
struct ld_info* info;
246
247
if (!(info = getinfo(handle)) || !(addr = getloc(info->ldinfo_textorg,info->ldinfo_dataorg,(char*)name)))
248
{
249
err = errno;
250
return 0;
251
}
252
return addr;
253
}
254
255
extern char* dlerror(void)
256
{
257
char* msg;
258
259
if (!err)
260
return 0;
261
msg = fmterror(err);
262
err = 0;
263
return msg;
264
}
265
266
#else
267
#if _hdr_dll && _lib_dllload
268
269
/*
270
* MVS
271
*/
272
273
# include <dll.h>
274
275
static int err;
276
277
extern void* dlopen(const char* path, int mode)
278
{
279
void* dll;
280
281
NoP(mode);
282
if (!(dll = (void*)dllload(path)))
283
err = errno;
284
return dll;
285
}
286
287
extern int dlclose(void* dll)
288
{
289
return 0;
290
}
291
292
extern void* dlsym(void* handle, const char* name)
293
{
294
void* addr;
295
296
if (!(addr = (void*)dllqueryfn(handle, (char*)name)))
297
err = errno;
298
return addr;
299
}
300
301
extern char* dlerror(void)
302
{
303
char* msg;
304
305
if (!err)
306
return 0;
307
msg = fmterror(err);
308
err = 0;
309
return msg;
310
}
311
312
#else
313
#if _hdr_mach_o_dyld
314
315
/*
316
* mac[h]
317
*/
318
319
# include <mach-o/dyld.h>
320
321
typedef const struct mach_header* NSImage;
322
323
typedef struct Dll_s
324
{
325
unsigned long magic;
326
NSImage image;
327
NSModule module;
328
char path[1];
329
} Dll_t;
330
331
#define DL_MAGIC 0x04190c04
332
#define DL_NEXT ((Dll_t*)RTLD_NEXT)
333
334
static const char* dlmessage = "no error";
335
336
static const char e_cover[] = T("cannot access covered library");
337
static const char e_handle[] = T("invalid handle");
338
static const char e_space[] = T("out of space");
339
static const char e_static[] = T("image statically linked");
340
static const char e_undefined[] = T("undefined symbol");
341
342
static Dll_t global = { DL_MAGIC };
343
344
static void undefined(const char* name)
345
{
346
}
347
348
static NSModule multiple(NSSymbol sym, NSModule om, NSModule nm)
349
{
350
return om;
351
}
352
353
static void linkedit(NSLinkEditErrors c, int n, const char* f, const char* m)
354
{
355
dlmessage = m;
356
}
357
358
static NSLinkEditErrorHandlers handlers =
359
{
360
undefined, multiple, linkedit
361
};
362
363
extern void* dlopen(const char* path, int mode)
364
{
365
Dll_t* dll;
366
int i;
367
NSObjectFileImage image;
368
369
static int init = 0;
370
371
if (!_dyld_present())
372
{
373
dlmessage = e_static;
374
return 0;
375
}
376
if (!init)
377
{
378
init = 1;
379
NSInstallLinkEditErrorHandlers(&handlers);
380
}
381
if (!path)
382
dll = &global;
383
else if (!(dll = newof(0, Dll_t, 1, strlen(path))))
384
{
385
dlmessage = e_space;
386
return 0;
387
}
388
else
389
{
390
switch (NSCreateObjectFileImageFromFile(path, &image))
391
{
392
case NSObjectFileImageSuccess:
393
dll->module = NSLinkModule(image, path, (mode & RTLD_LAZY) ? 0 : NSLINKMODULE_OPTION_BINDNOW);
394
NSDestroyObjectFileImage(image);
395
if (!dll->module)
396
{
397
free(dll);
398
return 0;
399
}
400
break;
401
case NSObjectFileImageInappropriateFile:
402
dll->image = NSAddImage(path, 0);
403
if (!dll->image)
404
{
405
free(dll);
406
return 0;
407
}
408
break;
409
default:
410
free(dll);
411
return 0;
412
}
413
strcpy(dll->path, path);
414
dll->magic = DL_MAGIC;
415
}
416
return (void*)dll;
417
}
418
419
extern int dlclose(void* handle)
420
{
421
Dll_t* dll = (Dll_t*)handle;
422
423
if (!dll || dll == DL_NEXT || dll->magic != DL_MAGIC)
424
{
425
dlmessage = e_handle;
426
return -1;
427
}
428
if (dll->module)
429
NSUnLinkModule(dll->module, 0);
430
free(dll);
431
return 0;
432
}
433
434
static NSSymbol
435
lookup(Dll_t* dll, const char* name)
436
{
437
unsigned long pun;
438
void* address;
439
440
if (dll == DL_NEXT)
441
{
442
if (!_dyld_func_lookup(name, &pun))
443
return 0;
444
address = (NSSymbol)pun;
445
}
446
else if (dll->module)
447
address = NSLookupSymbolInModule(dll->module, name);
448
else if (dll->image)
449
{
450
if (!NSIsSymbolNameDefinedInImage(dll->image, name))
451
return 0;
452
address = NSLookupSymbolInImage(dll->image, name, 0);
453
}
454
else
455
{
456
if (!NSIsSymbolNameDefined(name))
457
return 0;
458
address = NSLookupAndBindSymbol(name);
459
}
460
if (address)
461
address = NSAddressOfSymbol(address);
462
return address;
463
}
464
465
extern void* dlsym(void* handle, const char* name)
466
{
467
Dll_t* dll = (Dll_t*)handle;
468
NSSymbol address;
469
char buf[1024];
470
471
if (!dll || dll != DL_NEXT && (dll->magic != DL_MAGIC || !dll->image && !dll->module))
472
{
473
dlmessage = e_handle;
474
return 0;
475
}
476
if (!(address = lookup(dll, name)) && name[0] != '_' && strlen(name) < (sizeof(buf) - 1))
477
{
478
buf[0] = '_';
479
strcpy(buf + 1, name);
480
address = lookup(dll, buf);
481
}
482
if (!address)
483
{
484
dlmessage = dll == DL_NEXT ? e_cover : e_undefined;
485
return 0;
486
}
487
return (void*)address;
488
}
489
490
extern char* dlerror(void)
491
{
492
char* msg;
493
494
msg = (char*)dlmessage;
495
dlmessage = 0;
496
return msg;
497
}
498
499
#else
500
/*
501
* punt
502
*/
503
504
static int err;
505
506
extern void* dlopen(const char* path, int mode)
507
{
508
err = 1;
509
return 0;
510
}
511
512
extern int dlclose(void* dll)
513
{
514
err = 1;
515
return 0;
516
}
517
518
extern void* dlsym(void* handle, const char* name)
519
{
520
err = 1;
521
return 0;
522
}
523
524
extern char* dlerror(void)
525
{
526
if (!err)
527
return 0;
528
err = 0;
529
return "dynamic linking not supported";
530
}
531
532
#endif
533
#endif
534
#endif
535
#endif
536
#endif
537
538