1 /* $Id: load.c,v 1.30 2020-11-10 20:49:26 phil Exp $ */
2
3 /*
4 * load and run external functions for systems using v7/BSD style a.out
5 * -plb 11/9/93
6 *
7 * converted to loadx/os_load client 9/27/2020 -- not compiled
8 */
9
10 /*
11 * How it works;
12 *
13 * uses ld to create an OMAGIC (impure) a.out file (which need
14 * not load on a page boundary)
15 *
16 * runs ld twice; once to determine overall size, and a second time
17 * after load address known. This avoids needing to know about
18 * relocation bits which tend to be CPU/port dependant.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif /* HAVE_CONFIG_H defined */
24
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <a.out.h>
29
30 #include <stdlib.h> /* for malloc, getenv */
31 #include <stdio.h>
32
33 #include "h.h"
34 #include "snotypes.h"
35 #include "path.h" /* LD_PATH */
36 #include "lib.h" /* prototypes */
37 #include "str.h" /* strdup */
38
39 /* is this right? -- ok for OMAGIC */
40 #undef N_SIZE /* defined in NetBSD nlist.h */
41 #define N_SIZE(A) ((A).a_text + (A).a_data + (A).a_bss)
42
43 /* NetBSD compatibility */
44 #ifndef N_GETMAGIC
45 #define N_GETMAGIC(A) ((A).a_magic)
46 #endif /* N_GETMAGIC not defined */
47
48 #ifndef SYM_PREFIX
49 #define SYM_PREFIX "_" /* XXX most (all?) a.out systems? */
50 #endif /* SYM_PREFIX not defined */
51
52 static int
ld(char * output,char * addr,const char * func,char * input)53 ld(char *output, char *addr, const char *func, char *input) {
54 char command[1024]; /* XXX */
55
56 /*
57 * -N old, impure excutable (OMAGIC)
58 * -o output output file
59 * -T addr text addr (data follows)
60 * -e name entry point
61 * input relocatable object file (plus libs)!
62 */
63
64 /* XXX -A <path of mainbol executable??? */
65 /* XXX -lm -lc ?? */
66
67 sprintf( command, "%s -N -o %s -T %x -e %s%s %s",
68 LD_PATH, output, addr, SYM_PREFIX, func, input );
69
70 /* XXX use direct execvp of ld? pass argv? */
71 return system(command) == 0;
72 }
73
74 #define PATHLEN 256 /* XXX use MAXPATHLEN from param.h? */
75
76 /* "file" may include loader options (libs) after filename!! */
77 void *
os_load_library(const char * file)78 os_load_library(const char *file) {
79 return strdup(file);
80 }
81
82 void *
os_find_symbol(void * lib,const char * func,void ** stash)83 os_find_symbol(void *lib, const char *func, void **stash) {
84 struct exec a;
85 char *file = lib; /* strdup'ed above */
86 char temp[PATHLEN];
87 char *data;
88 void *entry;
89 long len; /* size of code+data */
90 int f;
91
92 /*
93 * "module" lookup does not pass "stash" pointer.
94 * To implement would need to:
95 * 1. link object file ONCE (on load), return pointer to struct
96 * 2. keep either: executable file, namelist file, or namelist in memory
97 *
98 * All of this only REALLY matters for snobol4 shared library, and
99 * the only a.out "BSD" systems I can think of that used a.out .so
100 * files (SunOS4, FreeBSD, NetBSD) had dlopen.
101 */
102 if (!stash)
103 return NULL;
104
105 sprintf( temp, "%s/snoXXXXXX", TMP_DIR);
106 mktemp( temp ); /* exists in v6 */
107
108 /* link once to get total size! */
109 if (!ld( temp, 0, func, file)) {
110 goto ld_error;
111 }
112
113 f = open(temp, O_RDONLY);
114 if (f < 0) {
115 /* XXX error message? */
116 goto ld_error;
117 }
118
119 if (read( f, &a, sizeof(a)) != sizeof(a)) {
120 /* XXX error message? */
121 goto header_error;
122 }
123
124 if (N_GETMAGIC(a) != OMAGIC) {
125 /* XXX error message? */
126 header_error:
127 close(f);
128 ld_error:
129 unlink(temp);
130 return NULL; /* fail */
131 }
132 close(f);
133 unlink(temp);
134
135 len = N_SIZE(a); /* total size (code+data+bss) */
136
137 /* fix here for NMAGIC or ZMAGIC; use valloc? */
138 data = malloc(len);
139 if (data == NULL) {
140 return NULL;
141 }
142
143 /* XXX need only zero bss! */
144 bzero( data, len );
145
146 /*
147 * could chain all of the following together in one big if stmt,
148 * but it would be a pain to debug!
149 */
150
151 /* re-link at new addr */
152 if (!ld( temp, data, fp->name, file) || (f = open(temp, 0)) < 0)
153 goto file_open_error;
154
155 if (read( f, &a, sizeof(a)) != sizeof(a))
156 goto data_read_error;
157
158 if (N_GETMAGIC(a) != OMAGIC || a.a_entry == 0 || N_SIZE(a) > len)
159 goto data_read_error;
160
161 if (read(f, data, len) != len) {
162 data_read_error:
163 close(f);
164 file_open_error:
165 unlink(temp);
166 free(data);
167 return NULL;
168 }
169 close(f);
170
171 *stash = data; /* for os_unload_function */
172 return (void *)a.a_entry;
173 }
174
175 void
os_unload_function(const char * name,void * stash)176 os_unload_function(const char *name, void *stash) {
177 (void) name;
178 if (stash)
179 free(stash);
180 }
181
182 void
os_unload_library(void * lib)183 os_unload_library(void *lib) {
184 free(lib); /* strdup'ed */
185 }
186