YAP 7.1.0
load_coff.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_coff.c *
12* comments: coff based dynamic loader of external routines *
13* *
14*************************************************************************/
15
16#include "Yap.h"
17#include "Yatom.h"
18#include "YapHeap.h"
19#include "Foreign.h"
20
21#ifdef COFF
22this code is no being maintained anymore
23#include <stdio.h>
24#include <fcntl.h>
25#include <sys/types.h>
26#include <sys/file.h>
27#include <sys/param.h>
28#include <sys/stat.h>
29#include <a.out.h>
30
31#define oktox(n) \
32 (0==stat(n,&stbuf)&&(stbuf.st_mode&S_IFMT)==S_IFREG&&0==access(n,X_OK))
33#define oktow(n) \
34 (0==stat(n,&stbuf)&&(stbuf.st_mode&S_IFMT)==S_IFDIR&&0==access(n,W_OK))
35
36#ifdef mips
37#define MAXSECTIONS 100
38#else
39#define MAXSECTIONS 20
40#endif /* mips */
41
42#ifdef sgi
43#include <symbol.h>
44#endif /* sgi */
45
46#define N_TXTOFF(x) (sizeof(struct filehdr)+(x).f_opthdr+(x).f_nscns*sizeof(struct scnhdr))
47
48
49/*
50 * YAP_FindExecutable(argv[0]) should be called on yap initialization to
51 * locate the executable of Yap
52*/
53char *
54Yap_FindExecutable(void)
55{
56 register char *cp, *cp2;
57 struct stat stbuf;
58
59
60 cp = (char *)getenv("PATH");
61 if (cp == NULL)
62 cp = ".:/usr/ucb:/bin:/usr/bin:/usr/local/bin";
63 if (*GLOBAL_argv[0] == '/') {
64 if (oktox(GLOBAL_argv[0])) {
65 strcpy(LOCAL_FileNameBuf, GLOBAL_argv[0]);
66 Yap_TrueFileName(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE);
67 return NULL;
68 }
69 }
70 if (*cp == ':')
71 cp++;
72 for (; *cp;) {
73 /*
74 * copy over current directory and then append
75 * argv[0]
76 */
77
78 for (cp2 = LOCAL_FileNameBuf; (*cp) != 0 && (*cp) != ':';)
79 *cp2++ = *cp++;
80 *cp2++ = '/';
81 strcpy(cp2, GLOBAL_argv[0]);
82 if (*cp)
83 cp++;
84 if (!oktox(LOCAL_FileNameBuf))
85 continue;
86 Yap_TrueFileName(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE);
87 return GLOBAL_Executable;
88 }
89 /* one last try for dual systems */
90 strcpy(LOCAL_FileNameBuf, GLOBAL_argv[0]);
91 Yap_TrueFileName(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE);
92 if (oktox(GLOBAL_Executable))
93 return GLOBAL_Executable;
94 else
95 Yap_Error(SYSTEM_ERROR_INTERNAL,MkAtomTerm(Yap_LookupAtom(GLOBAL_Executable)),
96 "cannot find file being executed");
97 return NULL;
98}
99
100
101void *
102Yap_LoadForeignFile(char *file, int flags)
103{
104 /* not implemented */
105 return NULL;
106}
107
108int
109Yap_CallForeignFile(void *handle, char *f)
110{
111 return FALSE;
112}
113
114int
115Yap_CloseForeignFile(void *handle)
116{
117 return -1;
118}
119
120/*
121 * LoadForeign(ofiles,libs,proc_name,init_proc) dynamically loads foreign
122 * code files and libraries and locates an initialization routine
123*/
124static Int
125LoadForeign(StringList ofiles,
126 StringList libs,
127 char *proc_name,
128 YapInitProc *init_proc)
129{
130 char command[2*PATH_MAX];
131 char o_files[1024]; /* list of objects we want to load
132 */
133 char l_files[1024]; /* list of libraries we want to
134 load */
135 char tmp_buff[32] = "/tmp/YAP_TMP_XXXXXX"; /* used for
136 mktemp */
137 char *tfile; /* name of temporary file */
138 int fildes; /* temp file descriptor */
139 struct aouthdr sysHeader;
140 struct filehdr fileHeader;
141 struct scnhdr sectionHeader[MAXSECTIONS];
142 struct exec header; /* header for loaded file */
143 unsigned long loadImageSize, firstloadImSz; /* size of image we will load */
144 char *FCodeBase; /* where we load foreign code */
145
146 /*
147 * put in a string the names of the files you want to load and of any
148 * libraries you want to use
149 */
150 /* files first */
151 *o_files = '\0';
152 {
153 StringList tmp = ofiles;
154
155 while(tmp != NULL) {
156 strcat(o_files," ");
157 strcat(o_files,AtomName(tmp->name));
158 tmp = tmp->next;
159 }
160 }
161 /* same_trick for libraries */
162 *l_files = '\0';
163 {
164 StringList tmp = libs;
165
166 while(tmp != NULL) {
167 strcat(l_files," ");
168 strcat(l_files,AtomName(tmp->name));
169 tmp = tmp->next;
170 }
171 }
172 /* next, create a temp file to serve as loader output */
173 tfile = mktemp(tmp_buff);
174
175 /* prepare the magic */
176 if (strlen(o_files) + strlen(l_files) + strlen(proc_name) +
177 strlen(GLOBAL_Executable) > 2*PATH_MAX) {
178 strcpy(LOCAL_ErrorSay, " too many parameters in load_foreign/3 ");
179 return LOAD_FAILLED;
180 }
181 sprintf(command, "/usr/bin/ld -N -A %s -o %s %s %s -lc",
182 GLOBAL_Executable,
183 tfile, o_files, l_files);
184 /* now, do the magic */
185 if (system(command) != 0) {
186 unlink(tfile);
187 strcpy(LOCAL_ErrorSay," ld returned error status in load_foreign_files ");
188 return LOAD_FAILLED;
189 }
190 /* now check the music has played */
191 if ((fildes = open(tfile, O_RDONLY)) < 0) {
192 strcpy(LOCAL_ErrorSay," unable to open temp file in load_foreign_files ");
193 return LOAD_FAILLED;
194 }
195 /* it did, get the mice */
196 /* first, get the header */
197 read(fildes, (char *) &fileHeader, sizeof(fileHeader));
198 read(fildes, (char *) &sysHeader, sizeof(sysHeader));
199 { int i;
200 for (i = 0; i < fileHeader.f_nscns; i++)
201 read(fildes, (char *) &sectionHeader[i],
202 sizeof(*sectionHeader));
203 }
204 close(fildes);
205 /* get the full size of what we need to load */
206 loadImageSize = sysHeader.tsize + sysHeader.dsize + sysHeader.bsize;
207#ifdef mips
208 /* add an extra page in mips machines */
209 loadImageSize += 4095 + 16;
210#else
211 /* add 16 just to play it safe */
212 loadImageSize += 16;
213#endif
214 /* keep this copy */
215 firstloadImSz = loadImageSize;
216 /* now fetch the space we need */
217 if (!(FCodeBase = Yap_AllocCodeSpace((int) loadImageSize))
218#ifdef pyr
219 || activate_code(ForeignCodeBase, u1)
220#endif /* pyr */
221 ) {
222 strcpy(LOCAL_ErrorSay," unable to allocate space for external code ");
223 return LOAD_FAILLED;
224 }
225#ifdef mips
226 FCodeBase = (char *) (Unsigned(FCodeBase + PAGESIZE - 1) & ~(PAGESIZE - 1));
227#endif
228
229 /* now, a new incantation to load the new foreign code */
230#ifdef convex
231 /* No -N flag in the Convex loader */
232 /* -T option does not want MallocBase bit set */
233 sprintf(command, "ld -x -A %s -T %lx -o %s -u %s %s %s -lc",
234 ostabf,
235 ((unsigned long) (((unsigned long) (ForeignCodeBase)) &
236 ((unsigned long) (~Yap_HeapBase))
237 )
238 ), tfile, entry_point, o_files, l_files);
239#else
240#ifdef mips
241 sprintf(command, "ld -systype bsd43 -N -A %s -T %lx -o %s -u %s %s %s -lc",
242 ostabf,
243 (unsigned long) ForeignCodeBase,
244 tfile, entry_point, o_files, l_files);
245#else
246 sprintf(command, "ld -N -A %s -T %lx -o %s -e %s -u _%s %s -lc",
247 ostabf,
248 (unsigned long) ForeignCodeBase,
249 tfile, entry_point, o_files, l_files);
250#endif /* mips */
251#endif /* convex */
252 /* and do it */
253 if (system(command) != 0) {
254 unlink(tfile);
255 strcpy(LOCAL_ErrorSay," ld returned error status in load_foreign_files ");
256 return LOAD_FAILLED;
257 }
258 if ((fildes = open(tfile, O_RDONLY)) < 0) {
259 strcpy(LOCAL_ErrorSay," unable to open temp file in load_foreign_files ");
260 return LOAD_FAILLED;
261 }
262 read(fildes, (char *) &fileHeader, sizeof(fileHeader));
263 read(fildes, (char *) &sysHeader, sizeof(sysHeader));
264 {
265 int i;
266 for (i = 0; i < fileHeader.f_nscns; i++)
267 read(fildes, (char *) &sectionHeader[i], sizeof(*sectionHeader));
268 }
269 loadImageSize = sysHeader.tsize + sysHeader.dsize + sysHeader.bsize;
270 if (firstloadImSz < loadImageSize) {
271 strcpy(LOCAL_ErrorSay," miscalculation in load_foreign/3 ");
272 return LOAD_FAILLED;
273 }
274 /* now search for our init function */
275 {
276 char entry_fun[256];
277 struct nlist func_info[2];
278#if defined(mips) || defined(I386)
279 char NAME1[128], NAME2[128];
280 func_info[0].n_name = NAME1;
281 func_info[1].n_name = NAME2;
282#endif /* COFF */
283 sprintf(entry_fun, "_%s", proc_name);
284 func_info[0].n_name = entry_fun;
285 func_info[1].n_name = NULL;
286 if (nlist(tfile, func_info) == -1) {
287 strcpy(LOCAL_ErrorSay," in nlist(3) ");
288 return LOAD_FAILLED;
289 }
290 if (func_info[0].n_type == 0) {
291 strcpy(LOCAL_ErrorSay," in nlist(3) ");
292 return LOAD_FAILLED;
293 }
294 *init_proc = (YapInitProc)(func_info[0].n_value);
295 }
296 /* ok, we got our init point */
297 /* now read our text */
298 lseek(fildes, (long)(N_TXTOFF(header)), 0);
299 {
300 unsigned int u1 = header.a_text + header.a_data;
301 read(fildes, (char *) FCodeBase, u1);
302 /* zero the BSS segment */
303 while (u1 < loadImageSize)
304 FCodeBase[u1++] = 0;
305 }
306 close(fildes);
307 unlink(tfile);
308 return LOAD_SUCCEEDED;
309}
310
311Int
312Yap_LoadForeign(StringList ofiles, StringList libs,
313 char *proc_name, YapInitProc *init_proc)
314{
315 return LoadForeign(ofiles, libs, proc_name, init_proc);
316}
317
318void
319Yap_ShutdownLoadForeign(void)
320{
321}
322
323Int
324Yap_ReLoadForeign(StringList ofiles, StringList libs,
325 char *proc_name, YapInitProc *init_proc)
326{
327 return(LoadForeign(ofiles,libs, proc_name, init_proc));
328}
329
330
331
332#endif
333
334
335
336
load_foreign_files/3 has works for the following configurations:
Main definitions.