1 /*
2 * $Id: udl.c,v 1.1 2005-09-18 22:05:41 dhmunro Exp $
3 * UNIX version of play dynamic linking operations
4 */
5 /* Copyright (c) 2005, The Regents of the University of California.
6 * All rights reserved.
7 * This file is part of yorick (http://yorick.sourceforge.net).
8 * Read the accompanying LICENSE file for details.
9 */
10
11 #include "config.h"
12
13 #include "playu.h"
14 #include "pstdlib.h"
15 #include <string.h>
16
17 #ifdef PLUG_HEADER
18 #include PLUG_HEADER
19 #endif
20
21 #if defined(PLUG_LIBDL)
22
23 #ifndef PLUG_SUFFIX
24 # define PLUG_SUFFIX ".so"
25 #endif
26
27 #ifndef PLUG_HEADER
28 #include <dlfcn.h>
29 #endif
30
31 #ifndef PLUG_FLAGS
32 # define PLUG_FLAGS RTLD_LAZY | RTLD_GLOBAL
33 #endif
34
35 void *
p_dlopen(const char * dlname)36 p_dlopen(const char *dlname)
37 {
38 void *handle = 0;
39 if (dlname && dlname[0]) {
40 char *name = p_strncat(u_pathname(dlname), PLUG_SUFFIX, 0);
41 handle = dlopen(name, PLUG_FLAGS);
42 p_free(name);
43 }
44 return handle;
45 }
46
47 int
p_dlsym(void * handle,const char * symbol,int type,void * paddr)48 p_dlsym(void *handle, const char *symbol, int type, void *paddr)
49 {
50 void **addr = paddr;
51 addr[0] = dlsym(handle, symbol);
52 /* correct way to detect failure if a==0 were legal:
53 * const char *msg = dlerror();
54 * if (msg) return 0;
55 */
56 return !addr[0];
57 }
58
59
60
61 #elif defined(PLUG_HPUX)
62
63 #define PLUG_SUFFIX ".sl"
64
65 #ifndef PLUG_HEADER
66 #include <dl.h>
67 #endif
68 #include <errno.h>
69
70 #ifndef PLUG_FLAGS
71 # define PLUG_FLAGS BIND_DEFERRED
72 #endif
73
74 void *
p_dlopen(const char * dlname)75 p_dlopen(const char *dlname)
76 {
77 void *handle = 0;
78 if (dlname && dlname[0]) {
79 char *name = p_strncat(u_pathname(dlname), PLUG_SUFFIX, 0);
80 handle = (void *)shl_load(name, PLUG_FLAGS, 0);
81 p_free(name);
82 }
83 return handle;
84 }
85
86 int
p_dlsym(void * handle,const char * symbol,int type,void * paddr)87 p_dlsym(void *handle, const char *symbol, int type, void *paddr)
88 {
89 void **addr = paddr;
90 short expect = type? ((type&1)? TYPE_DATA : TYPE_UNDEFINED) : TYPE_PROCEDURE;
91 int notok = shl_findsym(&handle, symbol, expect, paddr);
92 return notok || !addr[0];
93 }
94
95
96
97 #elif defined(PLUG_MACOSX)
98 /* Apple now deprecates this. At Mac OS X 10.4 and beyond, use PLUG_LIBDL.
99 * see https://developer.apple.com/library/mac/#qa/qa1180/_index.html
100 */
101
102 #define PLUG_SUFFIX ".so"
103
104 #ifndef PLUG_HEADER
105 #include <mach-o/dyld.h>
106 #endif
107
108 void *
p_dlopen(const char * dlname)109 p_dlopen(const char *dlname)
110 {
111 void *handle = 0;
112 if (dlname && dlname[0]) {
113 char *name = p_strncat(u_pathname(dlname), PLUG_SUFFIX, 0);
114 NSObjectFileImage file_image;
115 if (NSCreateObjectFileImageFromFile(name, &file_image) ==
116 NSObjectFileImageSuccess) {
117 handle = (void *)NSLinkModule(file_image, name,
118 NSLINKMODULE_OPTION_RETURN_ON_ERROR
119 | NSLINKMODULE_OPTION_PRIVATE);
120 NSDestroyObjectFileImage(file_image);
121 }
122 p_free(name);
123 }
124 return handle; /* actually type NSModule */
125 }
126
127 int
p_dlsym(void * handle,const char * symbol,int type,void * paddr)128 p_dlsym(void *handle, const char *symbol, int type, void *paddr)
129 {
130 void **addr = paddr;
131 addr[0] = 0;
132 if (symbol && symbol[0]) {
133 char *symname = p_strncat("_", symbol, 0);
134 NSSymbol sym = NSLookupSymbolInModule(handle, symname);
135 if (sym) addr[0] = NSAddressOfSymbol(sym);
136 p_free(symname);
137 }
138 return !addr[0];
139 }
140
141
142
143 #elif defined(PLUG_MACOSX_DYLIB)
144 /*
145 this is fossil code - it is correct, but I couldn't get the linker
146 to build a correct optimized .dylib for the cerfc example in extend/
147
148 a more careful reading of the Mach-O documentation (the tech note on
149 porting to UNIX in particular) suggests that plugins are supposed
150 to be implemented with the -bundle switch to the compiler, not .dylib
151 the required MACOSX_DEPLOYMENT_TARGET env var to libtool exists only
152 from 10.3 onward, so -bundle is the only possibility for <=10.2
153 */
154
155 #define PLUG_SUFFIX ".dylib"
156
157 #ifndef PLUG_HEADER
158 #include <mach-o/dyld.h>
159 #endif
160
161 #ifndef PLUG_FLAGS
162 # define PLUG_FLAGS NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
163 #endif
164
165 void *
p_dlopen(const char * dlname)166 p_dlopen(const char *dlname)
167 {
168 void *handle = 0;
169 if (dlname && dlname[0]) {
170 char *name = p_strncat(u_pathname(dlname), PLUG_SUFFIX, 0);
171 handle = (void *)NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
172 p_free(name);
173 }
174 return handle; /* actually type (struct mach_header *) */
175 }
176
177 int
p_dlsym(void * handle,const char * symbol,int type,void * paddr)178 p_dlsym(void *handle, const char *symbol, int type, void *paddr)
179 {
180 void **addr = paddr;
181 addr[0] = 0;
182 if (symbol && symbol[0]) {
183 char *symname = p_strncat("_", symbol, 0);
184 if (NSIsSymbolNameDefinedInImage(handle, symname)) {
185 NSSymbol nss =
186 NSLookupSymbolInImage(handle, symname, PLUG_FLAGS |
187 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
188 if (nss) addr[0] = NSAddressOfSymbol(nss);
189 }
190 p_free(symname);
191 }
192 return !addr[0];
193 }
194
195
196
197 #else
198
199 /* ARGSUSED */
200 void *
p_dlopen(const char * dlname)201 p_dlopen(const char *dlname)
202 {
203 return 0;
204 }
205
206 /* ARGSUSED */
207 int
p_dlsym(void * handle,const char * symbol,int type,void * paddr)208 p_dlsym(void *handle, const char *symbol, int type, void *paddr)
209 {
210 void **addr = paddr;
211 addr[0] = 0;
212 return 1;
213 }
214
215 #endif
216