YAP 7.1.0
load_dyld.c
1/*************************************************************************
2* *
3* YAP Prolog *
4* *
5* Yap Prolog was developed at NCCUP - Universidade do Porto *
6* *
7* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8* *
9**************************************************************************
10* *
11* File: load_dyld.c *
12* comments: dyld based dynamic loaderr of external routines *
13* tested on MacOS *
14*************************************************************************/
15
16#include "Yap.h"
17#include "Yatom.h"
18#include "YapHeap.h"
19#include "yapio.h"
20#include "Foreign.h"
21
22#if LOAD_DYLD
23
24#include <string.h>
25
26/* Code originally from Rex A. Dieter's posting in comp.sys.next.programmer
27 and from dynload_next.c in the Python sources
28*/
29#import <mach-o/dyld.h>
30
31
32
33static char *
34mydlerror(void)
35{
36 char *errString;
37 switch(LOCAL_dl_errno) {
38 default:
39 case NSObjectFileImageFailure:
40 case NSObjectFileImageFormat:
41 /* for these a message is printed on stderr by dyld */
42 errString = "Can't create object file image";
43 break;
44 case NSObjectFileImageSuccess:
45 errString = NULL;
46 break;
47 case NSObjectFileImageInappropriateFile:
48 errString = "Inappropriate file type for dynamic loading";
49 break;
50 case NSObjectFileImageArch:
51 errString = "Wrong CPU type in object file";
52 break;
53 case NSObjectFileImageAccess:
54 errString = "Can't read object file (no access)";
55 break;
56 }
57 return(errString);
58}
59
60
61/*
62 * YAP_FindExecutable(argv[0]) should be called on yap initialization to
63 * locate the executable of Yap
64*/
65char *
66Yap_FindExecutable(void)
67{
68 char path[1024];
69 uint32_t size = sizeof(path);
70 if (_NSGetExecutablePath(path, &size) == 0) {
71 char *rc = malloc(size+1);
72 strncpy(rc, path, size);
73 return rc;
74 } else {
75 char *rc = malloc(size+1);
76 if (_NSGetExecutablePath(rc, &size) == 0)
77 return "yap";
78 return rc;
79 }
80}
81
82
83static void *
84mydlopen(char *path)
85{
86 int dyld_result;
87 NSObjectFileImage ofile;
88 NSModule handle = NULL;
89 dyld_result = NSCreateObjectFileImageFromFile(path, &ofile);
90 if (dyld_result != NSObjectFileImageSuccess) {
91 LOCAL_dl_errno = dyld_result;
92 } else {
93 /* NSLinkModule will cause the run to abort on any link error's */
94 /* not very friendly but the error recovery functionality is limited */
95 handle = NSLinkModule(ofile, path, TRUE);
96 }
97 return handle;
98}
99
100static void *
101mydlsym(char *symbol)
102{
103 void *addr;
104 char funcname[256];
105
106#if HAVE_SNPRINTF
107 snprintf(funcname, sizeof(funcname), "_%.200s", symbol);
108#else
109 sprintf(funcname, "_%.200s", symbol);
110#endif
111 if (NSIsSymbolNameDefined(funcname))
112 addr = NSAddressOfSymbol(NSLookupAndBindSymbol(funcname));
113 else
114 addr = NULL;
115 return addr;
116}
117
118static int
119mydlclose(void *handle)
120{
121 NSUnLinkModule(handle, NSUNLINKMODULE_OPTION_NONE);
122 return TRUE;
123}
124
125void *
126Yap_LoadForeignFile(char *file, int flags)
127{
128 return (void *)mydlopen(file);
129}
130
131int
132Yap_CallForeignFile(void *handle, char *f)
133{
134 YapInitProc proc = (YapInitProc) mydlsym(f);
135 if (!proc)
136 return FALSE;
137 (*proc)();
138 return TRUE;
139}
140
141int
142Yap_CloseForeignFile(void *handle)
143{
144 return mydlclose(handle);
145}
146
147
148/*
149 * LoadForeign(ofiles,libs,proc_name,init_proc) dynamically loads foreign
150 * code files and libraries and locates an initialization routine
151*/
152static Int
153LoadForeign(StringList ofiles, StringList libs,
154 char *proc_name, YapInitProc *init_proc)
155{
156 int lvl = push_text_stack();
157 while (ofiles) {
158 void *handle;
159
160 /* mydlopen wants to follow the LD_CONFIG_PATH */
161 iconst char *file = AtomName(ofiles->name);
162 if (!(file=Yap_findFile(file, true) )) {
163 strcpy(LOCAL_ErrorSay, "%% Trying to open unexisting file in LoadForeign");
164 popen_text_stack(lvl);
165 return LOAD_FAILLED;
166 }
167 if((handle=mydlopen(file)) == 0)
168 {
169 fprintf(stderr,"calling dlopen with error %s\n", mydlerror());
170/* strcpy(LOCAL_ErrorSay,dlerror());*/
171 popen_text_stack(lvl);
172 return LOAD_FAILLED;
173 }
174
175 ofiles->handle = handle;
176
177 ofiles = ofiles->next;
178 }
179 /* load libraries first so that their symbols are available to
180 other routines */
181 while (libs) {
182 char *s = AtomName(lib->name);
183
184 if (ls[0] == '-') {
185 strcpy(LOCAL_FileNameBuf,"lib");
186 strcat(LOCAL_FileNameBuf,s+2);
187 strcat(LOCAL_FileNameBuf,".so");
188 } else {
189 strcpy(LOCAL_FileNameBuf,s);
190 }
191
192 if((libs->handle=mydlopen(LOCAL_FileNameBuf)) == NULL)
193 {
194 strcpy(LOCAL_ErrorSay,mydlerror());
195 popen_text_stack(lvl);
196 return LOAD_FAILLED;
197 }
198 libs = libs->next;
199 }
200
201 *init_proc = (YapInitProc) mydlsym(proc_name);
202
203 if(! *init_proc) {
204 strcpy(LOCAL_ErrorSay,"Could not locate initialization routine");
205 popen_text_stack(lvl);
206 return LOAD_FAILLED;
207 }
208
209 popen_text_stack(lvl);
210 return LOAD_SUCCEEDED;
211}
212
213Int
214Yap_LoadForeign(StringList ofiles, StringList libs,
215 char *proc_name, YapInitProc *init_proc)
216{
217 return LoadForeign(ofiles, libs, proc_name, init_proc);
218}
219
220void
221Yap_ShutdownLoadForeign(void)
222{
223 ForeignObj *f_code;
224
225 f_code = ForeignCodeLoaded;
226 while (f_code != NULL) {
227 StringList objs, libs;
228
229 objs = f_code->objs;
230 while (objs != NULL) {
231 if (mydlclose(objs->handle) != 0)
232 return; /* ERROR */
233 objs = objs->next;
234 }
235 libs = f_code->libs;
236 while (libs != NULL) {
237 if (mydlclose(libs->handle) != 0)
238 return; /* ERROR */
239 objs = libs->next;
240 }
241 f_code = f_code->next;
242 }
243}
244
245Int
246Yap_ReLoadForeign(StringList ofiles, StringList libs,
247 char *proc_name, YapInitProc *init_proc)
248{
249 return(LoadForeign(ofiles,libs, proc_name, init_proc));
250}
251
252#endif
load_foreign_files/3 has works for the following configurations:
Main definitions.