chiark / gitweb /
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 }