Initial revision
[ssr] / StraySrc / SDLS / cdll / c / binding
1 /*
2 * binding.c
3 *
4 * Create DLL header and things
5 *
6 * © 1994-1998 Straylight
7 */
8
9 /*----- Licensing note ----------------------------------------------------*
10 *
11 * This file is part of Straylight's Dynamic Linking System (SDLS)
12 *
13 * SDLS is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * SDLS is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with SDLS. If not, write to the Free Software Foundation,
25 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stddef.h>
32
33 #include "binding.h"
34 #include "readdef.h"
35 #include "aof/aof.h"
36 #include "aof/chunk.h"
37 #include "hashtable.h"
38 #include "error.h"
39
40 typedef struct
41 {
42 /* --- Basic parts of the header --- */
43
44 unsigned magic;
45 unsigned bversion;
46 unsigned name;
47 unsigned copyright;
48 unsigned version;
49 unsigned relocate;
50 unsigned stubs;
51 unsigned entries;
52 unsigned enames;
53 unsigned eveneer;
54 unsigned dllBase;
55 unsigned dllLimit;
56 unsigned instBase;
57 unsigned instLimit;
58
59 /* --- New bits added for v. 1.01 --- */
60
61 unsigned zinitBase;
62 unsigned zinitLimit;
63 unsigned appStub;
64 unsigned appNames;
65 }
66 bind__header;
67
68 typedef struct
69 {
70 aof_file f;
71 bind__header *h;
72 hashtable osym;
73 }
74 bind__thing;
75
76 #define bind__MAGIC 0x004c4c44
77 #define bind__VERSION 101
78
79 static unsigned int nextOrd;
80
81 static void bind__enames(char *p,unsigned ord,void *handle)
82 {
83 bind__thing *t=handle;
84 int o; /* dummy for the aof... macros */
85
86 if (ord!=0xFFFFFFFF)
87 {
88 while (ord>nextOrd)
89 {
90 aof_byte(1,t->f.area);
91 nextOrd++;
92 }
93 }
94 if (hash_find(t->osym,p))
95 {
96 aof_string(p,t->f.area);
97 t->h->entries++;
98 if (ord!=0xFFFFFFFF)
99 nextOrd=ord+1;
100 }
101 }
102
103 static void bind__count(char *p,unsigned ord,void *handle)
104 {
105 bind__thing *t=handle;
106 if (hash_find(t->osym,p))
107 t->h->entries++;
108 }
109
110 static void bind__entries(char *p,unsigned ord,void *handle)
111 {
112 bind__thing *t=handle;
113 static int entry[4]={0xE92D0007, /* STMFD sp!,{a1-a3} */
114 0xE59FC000}; /* LDR ip,=address */
115 char buf[256];
116 if (ord!=0xFFFFFFFF)
117 {
118 static int duff[4];
119 while (ord>nextOrd)
120 {
121 aof_add(duff,t->f.area);
122 nextOrd++;
123 }
124 }
125 if (hash_find(t->osym,p))
126 {
127 entry[2]=aof_branch(t->f.area->next+8,sizeof(bind__header));
128 aof_reloc(p,t->f.area->next+12,0,&t->f);
129 sprintf(buf,"_dllEntry_%s",p);
130 aof_addsym(buf,t->f.area->next,0,4,&t->f);
131 aof_add(entry,t->f.area);
132 if (ord!=0xFFFFFFFF)
133 nextOrd=ord+1;
134 }
135 }
136
137 static void bind__appEntries(char *p,unsigned ord,void *handle)
138 {
139 bind__thing *t=handle;
140 int zero=0;
141 if (ord!=0xFFFFFFFF)
142 {
143 while (ord>nextOrd)
144 {
145 aof_add(zero,t->f.area);
146 nextOrd++;
147 }
148 }
149 if (hash_find(t->osym,p))
150 {
151 aof_reloc(p,aof_add(zero,t->f.area),0,&t->f);
152 if (ord!=0xFFFFFFFF)
153 nextOrd=ord+1;
154 }
155 }
156
157 void binding(char *name,readdef_info *inf,hashtable osym)
158 {
159 FILE *fp;
160
161 if (!inf->apptbl)
162 {
163 /* --- Don't check this lot if you can help it --- */
164
165 if (!inf->name[0])
166 {
167 if (!(inf->errored & rd_name))
168 error(NONAME);
169 inf->errored|=rd_name;
170 }
171 if (inf->version==-1)
172 {
173 if (!(inf->errored & rd_version))
174 error(NOVERSION);
175 inf->errored|=rd_version;
176 inf->version=100;
177 }
178 if (!inf->copyright[0])
179 {
180 if (!(inf->errored & rd_cright))
181 error(NOCRIGHT);
182 inf->errored|=rd_cright;
183 }
184 if (inf->errored & rd_name)
185 return;
186 }
187
188 fp=fopen(name,"wb"); /* Open the output file */
189 if (!fp) /* If the file wasn't opened */
190 error(NOOPENOUT,name); /* Better give an error */
191 else
192 {
193 char _buf[sizeof(chunk_fixedHeader)+5*sizeof(chunk_tableEntry)];
194 chunk_header *h=(chunk_header *)&_buf; /* Allocate memory easily :-) */
195
196 aof_chunkinfo obj_idfn={0};
197 aof_chunkinfo obj_head={0};
198 aof_chunkinfo obj_area={0};
199 aof_chunkinfo obj_symt={0};
200 aof_chunkinfo obj_strt={0};
201 aof_chunkinfo reloc={0};
202 bind__thing t;
203
204 bind__header hdr;
205 int o;
206
207 static int prologue[]={0xE1A0000E, /* MOV a1,lr */
208 0xE1A0100A, /* MOV a2,sl */
209 0xE24F2058, /* ADR a3,header */
210 0xEF04A30A, /* SWI DLL_Prologue */
211 0xE1A0E000, /* MOV lr,a1 */
212 0xE8BD0007, /* LDMFD sp!,{a1-a3} */
213 0xE1A0F00C}; /* MOV pc,ip */
214
215 h->hdr.id=chunk_MAGIC; /* Fill in magic thingy */
216 h->hdr.maxChunks=h->hdr.numChunks=5; /* And number of chunks */
217
218 if (!inf->apptbl)
219 {
220 /* --- Don't set up the header if we won't need it --- */
221
222 hdr.magic=bind__MAGIC;
223 hdr.bversion=bind__VERSION;
224 hdr.version=inf->version;
225 hdr.relocate=0xea000000;
226 hdr.stubs=0;
227 hdr.entries=0;
228 hdr.dllBase=0;
229 hdr.dllLimit=0;
230 hdr.instBase=0;
231 hdr.instLimit=0;
232 hdr.zinitBase=0;
233 hdr.zinitLimit=0;
234 hdr.appStub=0;
235 hdr.appNames=0;
236 }
237
238 t.f.area=&obj_area;
239 t.h=&hdr;
240 t.osym=osym;
241 t.f.symt=&obj_symt;
242 t.f.strt=&obj_strt;
243 t.f.reloc=&reloc;
244
245 aof_string("Straylight Dynamic Link Library building system 1.01",
246 &obj_idfn);
247 aof_align(obj_idfn);
248
249 if (!inf->apptbl)
250 {
251 aof_add(hdr,&obj_area);
252 if (~inf->flags & rdFlag_shortEntry)
253 aof_add(prologue,&obj_area);
254 aof_int(0,&obj_strt);
255 aof_string("!!!DLL$$Header",&obj_strt);
256
257 hdr.name=aof_string(inf->name,&obj_area);
258 aof_roff(offsetof(bind__header,name),&t.f);
259 hdr.copyright=aof_string(inf->copyright,&obj_area);
260 aof_roff(offsetof(bind__header,copyright),&t.f);
261 hdr.enames=obj_area.next;
262 aof_roff(offsetof(bind__header,enames),&t.f);
263 nextOrd=0;
264 if (~inf->flags & rdFlag_noNames)
265 hash_enumOrdered(inf->sym,bind__enames,&t);
266 else
267 hash_enumOrdered(inf->sym,bind__count,&t);
268 if (inf->flags & rdFlag_shortEntry)
269 hdr.entries|=0x80000000u;
270 if (inf->flags & rdFlag_noNames)
271 hdr.entries|=0x40000000u;
272 aof_align(obj_area);
273 hdr.eveneer=obj_area.next;
274 aof_roff(offsetof(bind__header,eveneer),&t.f);
275 nextOrd=0;
276 if (~inf->flags & rdFlag_shortEntry)
277 {
278 hash_enumOrdered(inf->sym,bind__entries,&t);
279 hash_enumOrdered(inf->vsym,bind__entries,&t);
280 }
281 else
282 {
283 hash_enumOrdered(inf->sym,bind__appEntries,&t);
284 hash_enumOrdered(inf->vsym,bind__appEntries,&t);
285 }
286
287 aof_reloc_b("__RelocCode",offsetof(bind__header,relocate),&t.f);
288 if (~inf->flags & rdFlag_shortEntry)
289 aof_reloc("_kernel_init",offsetof(bind__header,stubs),1,&t.f);
290 aof_reloc("DLL$$ExternalTable$$Base",
291 offsetof(bind__header,dllBase),
292 1,
293 &t.f);
294 aof_reloc("DLL$$ExternalTable$$Limit",
295 offsetof(bind__header,dllLimit),
296 1,
297 &t.f);
298 aof_reloc("Image$$RW$$Base",offsetof(bind__header,instBase),0,&t.f);
299 aof_reloc("Image$$RW$$Limit",offsetof(bind__header,instLimit),0,&t.f);
300 aof_reloc("Image$$ZI$$Base",offsetof(bind__header,zinitBase),0,&t.f);
301 aof_reloc("Image$$ZI$$Limit",offsetof(bind__header,zinitLimit),0,&t.f);
302 aof_reloc("DLL$$AppEntryStubs",offsetof(bind__header,appStub),1,&t.f);
303 aof_reloc("DLL$$AppEntryNames",offsetof(bind__header,appNames),1,&t.f);
304
305 aof_fill(hdr,0,&obj_area);
306
307 {
308 aof_symbol sym={0};
309 sym.name=aof_string("_dll_findall",&obj_strt);
310 sym.defined=1;
311 sym.export=1;
312 sym.absolute=1;
313 sym.value=0;
314 aof_add(sym,&obj_symt);
315 }
316 }
317 else
318 {
319 aof_int(0,&obj_strt);
320 aof_string("DLL$$AppEntryDefinition",&obj_strt);
321
322 aof_addsym("_dll_appEntryStubs",
323 obj_area.next,
324 0,
325 4,
326 &t.f);
327 nextOrd=0;
328 if (~inf->flags & rdFlag_noNames)
329 hash_enumOrdered(inf->sym,bind__appEntries,&t);
330
331 aof_addsym("_dll_appEntryNames",
332 obj_area.next,
333 0,
334 4,
335 &t.f);
336 nextOrd=0;
337 hash_enumOrdered(inf->sym,bind__enames,&t);
338 { char c=0; aof_add(c,&obj_area); }
339 aof_align(obj_area);
340
341 /* --- Hack for link 5.00 --- *
342 *
343 * We IMPORT _dll_regAppEntry here so that link will grab the correct
344 * bits of DLLLib
345 */
346
347 {
348 aof_symbol sym={0};
349 sym.name=aof_string("_dll_regAppEntry",&obj_strt);
350 sym.defined=0;
351 sym.export=1;
352 aof_add(sym,&obj_symt);
353 }
354
355 }
356
357 aof_int((int)aof_RELOC,&obj_head);
358 aof_int(150,&obj_head);
359 aof_int(1,&obj_head);
360 aof_int(obj_symt.next/sizeof(aof_symbol),&obj_head);
361 aof_int(0,&obj_head);
362 aof_int(0,&obj_head);
363
364 aof_int(4,&obj_head);
365 aof_int(0x00002202,&obj_head);
366 aof_int(obj_area.next,&obj_head);
367 aof_int(reloc.next/8,&obj_head);
368 aof_int(0,&obj_head);
369
370 aof_addBlock(reloc.p,reloc.next,&obj_area);
371
372 aof_fill(obj_strt.next,0,&obj_strt);
373 aof_align(obj_strt);
374
375 memcpy(h->table[0].chunkName,"OBJ_IDFN",8);
376 memcpy(h->table[1].chunkName,"OBJ_HEAD",8);
377 memcpy(h->table[2].chunkName,"OBJ_AREA",8);
378 memcpy(h->table[3].chunkName,"OBJ_SYMT",8);
379 memcpy(h->table[4].chunkName,"OBJ_STRT",8);
380
381 o=sizeof(chunk_fixedHeader)+5*sizeof(chunk_tableEntry);
382
383 h->table[0].offset=o;
384 h->table[0].size=obj_idfn.next;
385 o+=obj_idfn.next;
386
387 h->table[1].offset=o;
388 h->table[1].size=obj_head.next;
389 o+=obj_head.next;
390
391 h->table[2].offset=o;
392 h->table[2].size=obj_area.next;
393 o+=obj_area.next;
394
395 h->table[3].offset=o;
396 h->table[3].size=obj_symt.next;
397 o+=obj_symt.next;
398
399 h->table[4].offset=o;
400 h->table[4].size=obj_strt.next;
401 o+=obj_strt.next;
402
403 fwrite(h,sizeof(chunk_fixedHeader)+5*sizeof(chunk_tableEntry),1,fp);
404 fwrite(obj_idfn.p,obj_idfn.next,1,fp);
405 fwrite(obj_head.p,obj_head.next,1,fp);
406 fwrite(obj_area.p,obj_area.next,1,fp);
407 fwrite(obj_symt.p,obj_symt.next,1,fp);
408 fwrite(obj_strt.p,obj_strt.next,1,fp);
409 fclose(fp);
410
411 free(obj_idfn.p);
412 free(obj_area.p);
413 free(obj_strt.p);
414 free(obj_head.p);
415 free(obj_symt.p);
416 }
417 }