chiark / gitweb /
Initial revision
[ssr] / StraySrc / SDLS / cdll / c / decode
1 /*
2  * decode.c
3  *
4  * Find all the symbols in an ALF or AOF file.
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
32 #include "decode.h"
33 #include "aof/chunk.h"
34 #include "aof/aof.h"
35 #include "aof/alf.h"
36 #include "error.h"
37
38 static int decode__findChunk(chunk_header *c,char *name)
39 {
40   int i;
41   for (i=0;i<c->hdr.maxChunks;i++)
42   {
43     if (c->table[i].offset && !memcmp(c->table[i].chunkName,name,8))
44       return (i);
45   }
46   return (-1);
47 }
48
49 static int decode__listALF(chunk_header *c,
50                            hashtable h,
51                            FILE *fp,
52                            char *name,
53                            int entry)
54 {
55   int size=c->table[entry].size;        /* Help the compiler a bit      */
56   char *data=malloc(size);              /* Allocate memory for chunk    */
57
58   name=name;
59
60   {
61     if (!data)
62       error(NOMEM);
63   }
64
65   {
66     /* --- Note to the squeamish --- *
67      *
68      * I've done naughty things with fpos_t here to avoid reading the file
69      * sequentially.  This file isn't doing anything particularly portable
70      * anyway, so this is no great hardship.
71      */
72
73     fpos_t off;                         /* To set file position         */
74     off.__lo=c->table[entry].offset;    /* Widge the position indicator */
75     fsetpos(fp,&off);                   /* Set the file offset nicely   */
76     fread(data,1,size,fp);              /* Read external names table    */
77   }
78
79   {
80     int i=0;                            /* Counter through data         */
81     alf_symTable *tbl;                  /* Pointer to actual structures */
82     while (i<size)                      /* Continue until no more       */
83     {
84       tbl=(alf_symTable *)(data+i);     /* Set up the pointer           */
85       if (!hash_add(h,tbl->data))       /* Try to add the symbol name   */
86         error(NOMEM);
87       i+=tbl->entryLength;              /* Bump the index along a bit   */
88     }
89   }
90
91   {
92     free(data);
93   }
94
95   return (0);
96 }
97
98 static int decode__listAOF(chunk_header *c,
99                            hashtable h,
100                            FILE *fp,
101                            char *name,
102                            int sym,
103                            int str)
104
105 {
106   int sizeSym=c->table[sym].size;       /* Help the compiler a bit      */
107   int sizeStr=c->table[str].size;       /* Help the compiler a bit      */
108   aof_symbol *symbol=malloc(sizeSym);   /* Memory for symbol table      */
109   char *string=malloc(sizeStr);         /* Memory for string table      */
110   int symbols;                          /* Number of symbol entries     */
111   int headoff=0;                        /* Offset to AOF header chunk   */
112   int err=0;                            /* No errors yet                */
113
114   /* --- Check we got the memory --- */
115
116   {
117     if (!symbol || !string)
118       error(NOMEM);
119   }
120
121   if (!err)
122   {
123     if (headoff=decode__findChunk(c,"OBJ_HEAD"),headoff==-1)
124     {
125       error(BADFILE,name);
126       err=1;
127     }
128   }
129
130   if (!err)
131   {
132     /* --- Note to the squeamish --- *
133      *
134      * I've done naughty things with fpos_t here to avoid reading the file
135      * sequentially.  This file isn't doing anything particularly portable
136      * anyway, so this is no great hardship.
137      */
138
139     fpos_t off;                         /* To set file position         */
140
141     off.__lo=c->table[headoff].offset+12l; /* Find number of symbols    */
142     fsetpos(fp,&off);                   /* Set the file offset nicely   */
143     fread(&symbols,sizeof(symbols),1,fp); /* Read symbol count          */
144     off.__lo=c->table[sym].offset;      /* Widge the position indicator */
145     fsetpos(fp,&off);                   /* Set the file offset nicely   */
146     fread(symbol,1,sizeSym,fp);         /* Read symbol table            */
147     off.__lo=c->table[str].offset;      /* Widge the position indicator */
148     fsetpos(fp,&off);                   /* Set the file offset nicely   */
149     fread(string,1,sizeStr,fp);         /* Read string table            */
150   }
151
152   if (!err)
153   {
154     int i;                              /* Counter through data         */
155     for (i=0;i<symbols;i++)
156     {
157       if (symbol[i].defined && symbol[i].export)
158       {
159         if (!hash_add(h,string+symbol[i].name))
160           error(NOMEM);
161       }
162     }
163   }
164
165   {
166     free(string);
167     free(symbol);
168   }
169
170   return (err);
171 }
172
173 int decode(hashtable h,char *filename)
174 {
175   chunk_header *chf=0;                  /* Ptr to block to read table   */
176   FILE *fp=fopen(filename,"rb");        /* Open for binary reading      */
177   int err=0;                            /* No errors yet                */
178
179   {
180     chunk_fixedHeader ch={0,0,0};       /* For reading in the header    */
181
182     if (!fp)                            /* If open failed,...           */
183     {
184       error(NOOPENIN,filename);         /* Report an error, and         */
185       err=1;                            /*   return gracefully          */
186     }
187     else
188     {
189       fread(&ch,sizeof(ch),1,fp);       /* Read the file's header       */
190       if (ch.id!=chunk_MAGIC)           /* Check it's a real chunk file */
191       {
192         error(BADFILE,filename);
193         err=1;
194       }
195       else
196       {
197         chf=malloc(sizeof(chunk_fixedHeader)+
198                    ch.maxChunks*sizeof(chunk_tableEntry));
199         if (!chf)                       /* If allocation failed         */
200           error(NOMEM);
201         chf->hdr=ch;
202         fread(chf->table,sizeof(chunk_tableEntry),ch.maxChunks,fp);
203       }
204     }
205   }
206
207   if (!err)
208   {
209     int index;                          /* Index of symbol table chunk  */
210     int string;                         /* Index of string table chunk  */
211
212     if (index=decode__findChunk(chf,"OFL_SYMT"),index!=-1)
213       decode__listALF(chf,h,fp,filename,index);
214     else if ( (index=decode__findChunk(chf,"OBJ_SYMT"),index!=-1) &&
215               (string=decode__findChunk(chf,"OBJ_STRT"),string!=-1))
216       decode__listAOF(chf,h,fp,filename,index,string);
217     else
218     {
219       error(BADFILE,filename);
220       err=1;
221     }
222   }
223
224   {
225     if (fp)
226       fclose(fp);                       /* Don't need this any more     */
227     free(chf);                          /* Get rid of that too          */
228   }
229
230   return (err);
231 }