/* * binding.c * * Create DLL header and things * * © 1994-1998 Straylight */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Dynamic Linking System (SDLS) * * SDLS is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * SDLS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with SDLS. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "binding.h" #include "readdef.h" #include "aof/aof.h" #include "aof/chunk.h" #include "hashtable.h" #include "error.h" typedef struct { /* --- Basic parts of the header --- */ unsigned magic; unsigned bversion; unsigned name; unsigned copyright; unsigned version; unsigned relocate; unsigned stubs; unsigned entries; unsigned enames; unsigned eveneer; unsigned dllBase; unsigned dllLimit; unsigned instBase; unsigned instLimit; /* --- New bits added for v. 1.01 --- */ unsigned zinitBase; unsigned zinitLimit; unsigned appStub; unsigned appNames; } bind__header; typedef struct { aof_file f; bind__header *h; hashtable osym; } bind__thing; #define bind__MAGIC 0x004c4c44 #define bind__VERSION 101 static unsigned int nextOrd; static void bind__enames(char *p,unsigned ord,void *handle) { bind__thing *t=handle; int o; /* dummy for the aof... macros */ if (ord!=0xFFFFFFFF) { while (ord>nextOrd) { aof_byte(1,t->f.area); nextOrd++; } } if (hash_find(t->osym,p)) { aof_string(p,t->f.area); t->h->entries++; if (ord!=0xFFFFFFFF) nextOrd=ord+1; } } static void bind__count(char *p,unsigned ord,void *handle) { bind__thing *t=handle; if (hash_find(t->osym,p)) t->h->entries++; } static void bind__entries(char *p,unsigned ord,void *handle) { bind__thing *t=handle; static int entry[4]={0xE92D0007, /* STMFD sp!,{a1-a3} */ 0xE59FC000}; /* LDR ip,=address */ char buf[256]; if (ord!=0xFFFFFFFF) { static int duff[4]; while (ord>nextOrd) { aof_add(duff,t->f.area); nextOrd++; } } if (hash_find(t->osym,p)) { entry[2]=aof_branch(t->f.area->next+8,sizeof(bind__header)); aof_reloc(p,t->f.area->next+12,0,&t->f); sprintf(buf,"_dllEntry_%s",p); aof_addsym(buf,t->f.area->next,0,4,&t->f); aof_add(entry,t->f.area); if (ord!=0xFFFFFFFF) nextOrd=ord+1; } } static void bind__appEntries(char *p,unsigned ord,void *handle) { bind__thing *t=handle; int zero=0; if (ord!=0xFFFFFFFF) { while (ord>nextOrd) { aof_add(zero,t->f.area); nextOrd++; } } if (hash_find(t->osym,p)) { aof_reloc(p,aof_add(zero,t->f.area),0,&t->f); if (ord!=0xFFFFFFFF) nextOrd=ord+1; } } void binding(char *name,readdef_info *inf,hashtable osym) { FILE *fp; if (!inf->apptbl) { /* --- Don't check this lot if you can help it --- */ if (!inf->name[0]) { if (!(inf->errored & rd_name)) error(NONAME); inf->errored|=rd_name; } if (inf->version==-1) { if (!(inf->errored & rd_version)) error(NOVERSION); inf->errored|=rd_version; inf->version=100; } if (!inf->copyright[0]) { if (!(inf->errored & rd_cright)) error(NOCRIGHT); inf->errored|=rd_cright; } if (inf->errored & rd_name) return; } fp=fopen(name,"wb"); /* Open the output file */ if (!fp) /* If the file wasn't opened */ error(NOOPENOUT,name); /* Better give an error */ else { char _buf[sizeof(chunk_fixedHeader)+5*sizeof(chunk_tableEntry)]; chunk_header *h=(chunk_header *)&_buf; /* Allocate memory easily :-) */ aof_chunkinfo obj_idfn={0}; aof_chunkinfo obj_head={0}; aof_chunkinfo obj_area={0}; aof_chunkinfo obj_symt={0}; aof_chunkinfo obj_strt={0}; aof_chunkinfo reloc={0}; bind__thing t; bind__header hdr; int o; static int prologue[]={0xE1A0000E, /* MOV a1,lr */ 0xE1A0100A, /* MOV a2,sl */ 0xE24F2058, /* ADR a3,header */ 0xEF04A30A, /* SWI DLL_Prologue */ 0xE1A0E000, /* MOV lr,a1 */ 0xE8BD0007, /* LDMFD sp!,{a1-a3} */ 0xE1A0F00C}; /* MOV pc,ip */ h->hdr.id=chunk_MAGIC; /* Fill in magic thingy */ h->hdr.maxChunks=h->hdr.numChunks=5; /* And number of chunks */ if (!inf->apptbl) { /* --- Don't set up the header if we won't need it --- */ hdr.magic=bind__MAGIC; hdr.bversion=bind__VERSION; hdr.version=inf->version; hdr.relocate=0xea000000; hdr.stubs=0; hdr.entries=0; hdr.dllBase=0; hdr.dllLimit=0; hdr.instBase=0; hdr.instLimit=0; hdr.zinitBase=0; hdr.zinitLimit=0; hdr.appStub=0; hdr.appNames=0; } t.f.area=&obj_area; t.h=&hdr; t.osym=osym; t.f.symt=&obj_symt; t.f.strt=&obj_strt; t.f.reloc=&reloc; aof_string("Straylight Dynamic Link Library building system 1.01", &obj_idfn); aof_align(obj_idfn); if (!inf->apptbl) { aof_add(hdr,&obj_area); if (~inf->flags & rdFlag_shortEntry) aof_add(prologue,&obj_area); aof_int(0,&obj_strt); aof_string("!!!DLL$$Header",&obj_strt); hdr.name=aof_string(inf->name,&obj_area); aof_roff(offsetof(bind__header,name),&t.f); hdr.copyright=aof_string(inf->copyright,&obj_area); aof_roff(offsetof(bind__header,copyright),&t.f); hdr.enames=obj_area.next; aof_roff(offsetof(bind__header,enames),&t.f); nextOrd=0; if (~inf->flags & rdFlag_noNames) hash_enumOrdered(inf->sym,bind__enames,&t); else hash_enumOrdered(inf->sym,bind__count,&t); if (inf->flags & rdFlag_shortEntry) hdr.entries|=0x80000000u; if (inf->flags & rdFlag_noNames) hdr.entries|=0x40000000u; aof_align(obj_area); hdr.eveneer=obj_area.next; aof_roff(offsetof(bind__header,eveneer),&t.f); nextOrd=0; if (~inf->flags & rdFlag_shortEntry) { hash_enumOrdered(inf->sym,bind__entries,&t); hash_enumOrdered(inf->vsym,bind__entries,&t); } else { hash_enumOrdered(inf->sym,bind__appEntries,&t); hash_enumOrdered(inf->vsym,bind__appEntries,&t); } aof_reloc_b("__RelocCode",offsetof(bind__header,relocate),&t.f); if (~inf->flags & rdFlag_shortEntry) aof_reloc("_kernel_init",offsetof(bind__header,stubs),1,&t.f); aof_reloc("DLL$$ExternalTable$$Base", offsetof(bind__header,dllBase), 1, &t.f); aof_reloc("DLL$$ExternalTable$$Limit", offsetof(bind__header,dllLimit), 1, &t.f); aof_reloc("Image$$RW$$Base",offsetof(bind__header,instBase),0,&t.f); aof_reloc("Image$$RW$$Limit",offsetof(bind__header,instLimit),0,&t.f); aof_reloc("Image$$ZI$$Base",offsetof(bind__header,zinitBase),0,&t.f); aof_reloc("Image$$ZI$$Limit",offsetof(bind__header,zinitLimit),0,&t.f); aof_reloc("DLL$$AppEntryStubs",offsetof(bind__header,appStub),1,&t.f); aof_reloc("DLL$$AppEntryNames",offsetof(bind__header,appNames),1,&t.f); aof_fill(hdr,0,&obj_area); { aof_symbol sym={0}; sym.name=aof_string("_dll_findall",&obj_strt); sym.defined=1; sym.export=1; sym.absolute=1; sym.value=0; aof_add(sym,&obj_symt); } } else { aof_int(0,&obj_strt); aof_string("DLL$$AppEntryDefinition",&obj_strt); aof_addsym("_dll_appEntryStubs", obj_area.next, 0, 4, &t.f); nextOrd=0; if (~inf->flags & rdFlag_noNames) hash_enumOrdered(inf->sym,bind__appEntries,&t); aof_addsym("_dll_appEntryNames", obj_area.next, 0, 4, &t.f); nextOrd=0; hash_enumOrdered(inf->sym,bind__enames,&t); { char c=0; aof_add(c,&obj_area); } aof_align(obj_area); /* --- Hack for link 5.00 --- * * * We IMPORT _dll_regAppEntry here so that link will grab the correct * bits of DLLLib */ { aof_symbol sym={0}; sym.name=aof_string("_dll_regAppEntry",&obj_strt); sym.defined=0; sym.export=1; aof_add(sym,&obj_symt); } } aof_int((int)aof_RELOC,&obj_head); aof_int(150,&obj_head); aof_int(1,&obj_head); aof_int(obj_symt.next/sizeof(aof_symbol),&obj_head); aof_int(0,&obj_head); aof_int(0,&obj_head); aof_int(4,&obj_head); aof_int(0x00002202,&obj_head); aof_int(obj_area.next,&obj_head); aof_int(reloc.next/8,&obj_head); aof_int(0,&obj_head); aof_addBlock(reloc.p,reloc.next,&obj_area); aof_fill(obj_strt.next,0,&obj_strt); aof_align(obj_strt); memcpy(h->table[0].chunkName,"OBJ_IDFN",8); memcpy(h->table[1].chunkName,"OBJ_HEAD",8); memcpy(h->table[2].chunkName,"OBJ_AREA",8); memcpy(h->table[3].chunkName,"OBJ_SYMT",8); memcpy(h->table[4].chunkName,"OBJ_STRT",8); o=sizeof(chunk_fixedHeader)+5*sizeof(chunk_tableEntry); h->table[0].offset=o; h->table[0].size=obj_idfn.next; o+=obj_idfn.next; h->table[1].offset=o; h->table[1].size=obj_head.next; o+=obj_head.next; h->table[2].offset=o; h->table[2].size=obj_area.next; o+=obj_area.next; h->table[3].offset=o; h->table[3].size=obj_symt.next; o+=obj_symt.next; h->table[4].offset=o; h->table[4].size=obj_strt.next; o+=obj_strt.next; fwrite(h,sizeof(chunk_fixedHeader)+5*sizeof(chunk_tableEntry),1,fp); fwrite(obj_idfn.p,obj_idfn.next,1,fp); fwrite(obj_head.p,obj_head.next,1,fp); fwrite(obj_area.p,obj_area.next,1,fp); fwrite(obj_symt.p,obj_symt.next,1,fp); fwrite(obj_strt.p,obj_strt.next,1,fp); fclose(fp); free(obj_idfn.p); free(obj_area.p); free(obj_strt.p); free(obj_head.p); free(obj_symt.p); } }