2ee739cc |
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 | } |