chiark / gitweb /
Initial revision
[ssr] / StraySrc / SDLS / cdll / c / dissect
1 /*
2  * dissect an aof file into areas
3  */
4
5 /*----- Licensing note ----------------------------------------------------*
6  *
7  * This file is part of Straylight's Dynamic Linking System (SDLS)
8  *
9  * SDLS is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2, or (at your option)
12  * any later version.
13  *
14  * SDLS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with SDLS.  If not, write to the Free Software Foundation,
21  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22  */
23
24 #include "aof/chunk.h"
25
26 #define aof_RELOC (0xC5E2D080ul)        /* Relocatable object type      */
27
28 typedef struct
29 {
30   unsigned long type;                   /* Type of object file          */
31   int version;                          /* Version number of the format */
32   int areas;                            /* Number of AREAs defined      */
33   int symbols;                          /* Number of symbols in table   */
34   int entryArea;                        /* Index of AREA with ENTRY att */
35   int entryOff;                         /* Offset in AREA for ENTRY     */
36 }
37 aof_fixedHeader;
38
39 typedef struct
40 {
41   int name;                             /* AREA name (OBJ_STRT offset)  */
42
43   int alignment                 :8;     /* AREA alignment (must be 2)   */
44
45   int                           :1;     /* Reserved bit                 */
46   int code                      :1;     /* AREA contains code           */
47   int common                    :1;     /* Common AREA definition       */
48   int commonRef                 :1;     /* Reference to common AREA     */
49   int zinit                     :1;     /* AREA is zero-initialised     */
50   int readonly                  :1;     /* AREA is (sort-of) readonly   */
51   int                           :1;     /* Reserved bit                 */
52   int debug                     :1;     /* AREA contains debug tables   */
53   int                           :16;    /* Reserved shortword           */
54
55   int size;                             /* Size of this AREA            */
56   int relocs;                           /* Number of relocations        */
57   int                           :32;    /* Reserved word                */
58 }
59 aof_areaEntry;
60
61 typedef struct
62 {
63   aof_fixedHeader hdr;                  /* The fixed header info        */
64   aof_areaEntry table[1];               /* AREA table (unsized array)   */
65 }
66 aof_header;
67
68 typedef struct
69 {
70   int name;                             /* Name string table entry      */
71
72   int defined                   :1;     /* Symbol defined in file       */
73   int export                    :1;     /* Symbol is exported globally  */
74   int absolute                  :1;     /* Symbol not relative to AREA  */
75   int ignoreCase                :1;     /* Symbol is not case sensitive */
76   int weak                      :1;     /* Symbol is weak external ref  */
77   int strong                    :1;     /* Symbol is strong global      */
78   int common                    :1;     /* Symbol is in a common AREA   */
79   int                           :32-7;  /* Pad out to integer boundary  */
80
81   int value;                            /* Value of the symbol          */
82   int area;                             /* Offset of AREA name          */
83 }
84 aof_symbol;
85
86 typedef struct
87 {
88   int offset;                           /* Offset of word to relocate   */
89   union
90   {
91     struct
92     {
93       int symbol                :16;    /* Symbol to relocate by/to     */
94       int field                 :2;     /* Field size to alter          */
95       int type                  :1;     /* Relocation type              */
96       int symreloc              :1;     /* Relocation is symbol-relative*/
97       int                       :12;    /* Reserved bits                */
98     }
99     type_1;                             /* Type 1 relocation directive  */
100
101     struct
102     {
103       int symbol                :24;    /* Symbol to relocate by/to     */
104       int field                 :2;     /* Field size to alter          */
105       int type                  :1;     /* Relocation type              */
106       int symreloc              :1;     /* Relocation is symbol-relative*/
107       int                       :3;     /* Reserved bits                */
108       int set_me                :1;     /* Set this bit for type 2      */
109     }
110     type_2;                             /* Type 2 relocation directive  */
111   }
112   t;
113 }
114 aof_relocstr;
115
116 enum
117 {
118   aof_BYTE,
119   aof_HALFWORD,
120   aof_FULLWORD
121 };
122
123 enum
124 {
125   aof_ADDITIVE,
126   aof_PCRELATIVE
127 };
128
129 #include <stdlib.h>
130 #include <stdio.h>
131 #include <string.h>
132 #include <ctype.h>
133 #include <stdarg.h>
134
135 static char *nicely(char *name)
136 {
137   char *p=name;
138   while (*name)
139   {
140     if (!isalnum(*name))
141       *name='_';
142     name++;
143   }
144   if (strlen(p)>10)
145     p[10]=0;
146   return (p);
147 }
148
149 static int oscli(char *cmd,...)
150 {
151   char buffer[256];
152   va_list ap;
153   va_start(ap,cmd);
154   vsprintf(buffer,cmd,ap);
155   va_end(ap);
156   return (system(buffer));
157 }
158
159 static int findChunk(chunk_header *c,char *name)
160 {
161   int i;
162   for (i=0;i<c->hdr.maxChunks;i++)
163   {
164     if (c->table[i].offset && !memcmp(c->table[i].chunkName,name,8))
165       return (i);
166   }
167   return (-1);
168 }
169
170 static void get(void *p,FILE *fp,size_t size,size_t offset)
171 {
172   fpos_t off;
173   off.__lo=offset;
174   fsetpos(fp,&off);
175   fread(p,size,1,fp);
176 }
177
178 static int dissect(char *aof,char *dir)
179 {
180   FILE *fp;
181   FILE *out;
182   chunk_fixedHeader ch={0,0,0};
183   chunk_header *chf;
184   aof_header *header;
185   char *area;
186   char *string;
187   int h;
188   int a;
189   int s;
190   int bit=0;
191   char name[256];
192   int i;
193
194   oscli("cdir %s",dir);
195   fp=fopen(aof,"rb");
196   if (!fp)
197   {
198     fprintf(stderr,"couldn't open '%s'\n",aof);
199     return (1);
200   }
201   fread(&ch,sizeof(ch),1,fp);
202   if (ch.id!=chunk_MAGIC)
203   {
204     fprintf(stderr,"bad aof '%s'\n",aof);
205     return (1);
206   }
207   chf=malloc(sizeof(chunk_fixedHeader)+
208              ch.maxChunks*sizeof(chunk_tableEntry));
209   if (!chf)
210   {
211     fprintf(stderr,"no memory\n");
212     exit(1);
213   }
214   chf->hdr=ch;
215   fread(chf->table,sizeof(chunk_tableEntry),ch.maxChunks,fp);
216
217   h=findChunk(chf,"OBJ_HEAD");
218   a=findChunk(chf,"OBJ_AREA");
219   s=findChunk(chf,"OBJ_STRT");
220   if (h==-1 || a==-1 || s==-1)
221   {
222     fprintf(stderr,"bad aof '%s'\n",aof);
223     return (1);
224   }
225
226   header=malloc(chf->table[h].size);
227   area=malloc(chf->table[a].size);
228   string=malloc(chf->table[s].size);
229   if (!header || !area || !string)
230   {
231     fprintf(stderr,"no memory\n");
232     exit(1);
233   }
234
235   get(header,fp,chf->table[h].size,chf->table[h].offset);
236   get(area,fp,chf->table[a].size,chf->table[a].offset);
237   get(string,fp,chf->table[s].size,chf->table[s].offset);
238
239   for (i=0;i<header->hdr.areas;i++)
240   {
241     if (header->table[i].zinit)
242       continue;
243     sprintf(name,"%s.%s",dir,nicely(string+header->table[i].name));
244     out=fopen(name,"wb");
245     if (!out)
246     {
247       fprintf(stderr,"couldn't write '%s'\n",name);
248       continue;
249     }
250     fwrite(area+bit,1,header->table[i].size,out);
251     bit+=header->table[i].size+header->table[i].relocs*8;
252     fclose(out);
253   }
254   return (0);
255 }
256
257 int main(int argc,char *argv[])
258 {
259   if (argc!=3)
260   {
261     fprintf(stderr,"dissect <aof> <dir>\n");
262     exit(1);
263   }
264   return (dissect(argv[1],argv[2]));
265 }