Mercurial > hg-old > index.cgi
comparison lwlink/trunk/src/readfiles.c @ 116:817ab0e124fa
reading files implemented
author | lost |
---|---|
date | Wed, 21 Jan 2009 03:15:49 +0000 |
parents | |
children | d450943305a7 |
comparison
equal
deleted
inserted
replaced
115:776d8bea5b46 | 116:817ab0e124fa |
---|---|
1 /* | |
2 readfiles.c | |
3 Copyright © 2008 William Astle | |
4 | |
5 This file is part of LWLINK. | |
6 | |
7 LWLINK is free software: you can redistribute it and/or modify it under the | |
8 terms of the GNU General Public License as published by the Free Software | |
9 Foundation, either version 3 of the License, or (at your option) any later | |
10 version. | |
11 | |
12 This program is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
15 more details. | |
16 | |
17 You should have received a copy of the GNU General Public License along with | |
18 this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 | |
21 Reads input files | |
22 | |
23 */ | |
24 | |
25 #ifdef HAVE_CONFIG_H | |
26 #include "config.h" | |
27 #endif | |
28 | |
29 #include <argp.h> | |
30 #include <errno.h> | |
31 #include <stdio.h> | |
32 #include <stdlib.h> | |
33 | |
34 #include "lwlink.h" | |
35 #include "util.h" | |
36 | |
37 void read_lwobj16v0(fileinfo_t *fn); | |
38 | |
39 /* | |
40 The logic of reading the entire file into memory is simple. All the symbol | |
41 names in the file are NUL terminated strings and can be used directly without | |
42 making additional copies. | |
43 */ | |
44 void read_files(void) | |
45 { | |
46 int i; | |
47 long size; | |
48 FILE *f; | |
49 long bread; | |
50 for (i = 0; i < ninputfiles; i++) | |
51 { | |
52 f = fopen(inputfiles[i] -> filename, "rb"); | |
53 if (!f) | |
54 { | |
55 fprintf(stderr, "Can't open file %s:", inputfiles[i] -> filename); | |
56 perror(""); | |
57 exit(1); | |
58 } | |
59 fseek(f, 0, SEEK_END); | |
60 size = ftell(f); | |
61 rewind(f); | |
62 | |
63 inputfiles[i] -> filedata = lw_malloc(size); | |
64 inputfiles[i] -> filesize = size; | |
65 | |
66 bread = fread(inputfiles[i] -> filedata, 1, size, f); | |
67 if (bread < size) | |
68 { | |
69 fprintf(stderr, "Short read on file %s (%ld/%ld):", inputfiles[i] -> filename, bread, size); | |
70 perror(""); | |
71 exit(1); | |
72 } | |
73 | |
74 fclose(f); | |
75 | |
76 if (!memcmp(inputfiles[i] -> filedata, "LWOBJ16", 8)) | |
77 { | |
78 // read v0 LWOBJ16 file | |
79 read_lwobj16v0(inputfiles[i]); | |
80 } | |
81 else | |
82 { | |
83 fprintf(stderr, "%s: unknown file format\n", inputfiles[i] -> filename); | |
84 exit(1); | |
85 } | |
86 } | |
87 } | |
88 | |
89 // this macro is used to bail out if we run off the end of the file data | |
90 // while parsing - it keeps the code below cleaner | |
91 #define NEXTBYTE() do { cc++; if (cc >= fn -> filesize) { fprintf(stderr, "%s: invalid file format\n", fn -> filename); exit(1); } } while (0) | |
92 // this macro is used to refer to the current byte in the stream | |
93 #define CURBYTE() (fn -> filedata[cc]) | |
94 // this one will leave the input pointer past the trailing NUL | |
95 #define CURSTR() read_lwobj16v0_str(&cc, fn) | |
96 unsigned char *read_lwobj16v0_str(long *cc1, fileinfo_t *fn) | |
97 { | |
98 int cc = *cc1; | |
99 unsigned char *fp; | |
100 fp = &CURBYTE(); | |
101 while (CURBYTE()) | |
102 NEXTBYTE(); | |
103 NEXTBYTE(); | |
104 *cc1 = cc; | |
105 return fp; | |
106 } | |
107 // the function below can be switched to dealing with data coming from a | |
108 // source other than an in-memory byte pool by adjusting the input data | |
109 // in "fn" and the above two macros | |
110 void read_lwobj16v0(fileinfo_t *fn) | |
111 { | |
112 unsigned char *fp; | |
113 long cc; | |
114 section_t *s; | |
115 int val; | |
116 symtab_t *se; | |
117 | |
118 // start reading *after* the magic number | |
119 cc = 7; | |
120 | |
121 // init data | |
122 fn -> sections = NULL; | |
123 fn -> nsections = 0; | |
124 | |
125 while (1) | |
126 { | |
127 NEXTBYTE(); | |
128 // bail out if no more sections | |
129 if (!(CURBYTE())) | |
130 break; | |
131 | |
132 fp = CURSTR(); | |
133 | |
134 // we now have a section name in fp | |
135 // create new section entry | |
136 fn -> sections = lw_realloc(fn -> sections, sizeof(section_t) * (fn -> nsections + 1)); | |
137 s = &(fn -> sections[fn -> nsections]); | |
138 fn -> nsections += 1; | |
139 | |
140 s -> localsyms = NULL; | |
141 s -> flags = 0; | |
142 s -> codesize = 0; | |
143 s -> name = fp; | |
144 s -> loadaddress = 0; | |
145 s -> localsyms = NULL; | |
146 s -> exportedsyms = NULL; | |
147 s -> incompletes = NULL; | |
148 | |
149 // read flags | |
150 while (CURBYTE()) | |
151 { | |
152 switch (CURBYTE()) | |
153 { | |
154 case 0x01: | |
155 s -> flags |= SECTION_BSS; | |
156 break; | |
157 | |
158 default: | |
159 fprintf(stderr, "%s (%s): unrecognized section flag %02X\n", fn -> filename, s -> name, (int)(CURBYTE())); | |
160 exit(1); | |
161 } | |
162 NEXTBYTE(); | |
163 } | |
164 // skip NUL terminating flags | |
165 NEXTBYTE(); | |
166 | |
167 // now parse the local symbol table | |
168 while (CURBYTE()) | |
169 { | |
170 fp = CURSTR(); | |
171 | |
172 // fp is the symbol name | |
173 val = (CURBYTE()) << 8; | |
174 NEXTBYTE(); | |
175 val |= (CURBYTE()); | |
176 NEXTBYTE(); | |
177 // val is now the symbol value | |
178 | |
179 // create symbol table entry | |
180 se = lw_malloc(sizeof(symtab_t)); | |
181 se -> next = s -> localsyms; | |
182 s -> localsyms = se; | |
183 se -> sym = fp; | |
184 se -> offset = val; | |
185 se -> realval = val; | |
186 } | |
187 | |
188 // now parse the exported symbol table | |
189 while (CURBYTE()) | |
190 { | |
191 fp = CURSTR(); | |
192 | |
193 // fp is the symbol name | |
194 val = (CURBYTE()) << 8; | |
195 NEXTBYTE(); | |
196 val |= (CURBYTE()); | |
197 NEXTBYTE(); | |
198 // val is now the symbol value | |
199 | |
200 // create symbol table entry | |
201 se = lw_malloc(sizeof(symtab_t)); | |
202 se -> next = s -> exportedsyms; | |
203 s -> localsyms = se; | |
204 se -> sym = fp; | |
205 se -> offset = val; | |
206 se -> realval = val; | |
207 } | |
208 | |
209 // now parse the incomplete references and make a list of | |
210 // external references that need resolution | |
211 while (CURBYTE()) | |
212 { | |
213 reloc_t *rp; | |
214 lw_expr_term_t *term; | |
215 | |
216 // we have a reference | |
217 rp = lw_malloc(sizeof(reloc_t)); | |
218 rp -> next = s -> incompletes; | |
219 s -> incompletes = rp; | |
220 rp -> offset = 0; | |
221 rp -> expr = lw_expr_stack_create(); | |
222 | |
223 // parse the expression | |
224 while (CURBYTE()) | |
225 { | |
226 int tt = CURBYTE(); | |
227 NEXTBYTE(); | |
228 switch (tt) | |
229 { | |
230 case 0x01: | |
231 // 16 bit integer | |
232 tt = CURBYTE() << 8; | |
233 NEXTBYTE(); | |
234 tt |= CURBYTE(); | |
235 NEXTBYTE(); | |
236 // normalize for negatives... | |
237 if (tt > 0x7fff) | |
238 tt -= 0x10000; | |
239 term = lw_expr_term_create_int(tt); | |
240 break; | |
241 | |
242 case 0x02: | |
243 // external symbol reference | |
244 term = lw_expr_term_create_sym(CURSTR(), 0); | |
245 break; | |
246 | |
247 case 0x03: | |
248 // internal symbol reference | |
249 term = lw_expr_term_create_sym(CURSTR(), 1); | |
250 break; | |
251 | |
252 case 0x04: | |
253 // operator | |
254 term = lw_expr_term_create_oper(CURBYTE()); | |
255 NEXTBYTE(); | |
256 break; | |
257 | |
258 case 0x05: | |
259 // section base reference (NULL internal reference is | |
260 // the section base address | |
261 term = lw_expr_term_create_sym(NULL, 0); | |
262 break; | |
263 | |
264 default: | |
265 fprintf(stderr, "%s (%s): bad relocation expression\n", fn -> filename, s -> name); | |
266 exit(1); | |
267 } | |
268 lw_expr_stack_push(rp -> expr, term); | |
269 lw_expr_term_free(term); | |
270 } | |
271 } | |
272 // skip the NUL terminatin | |
273 NEXTBYTE(); | |
274 | |
275 // now set code location and size and verify that the file | |
276 // contains data going to the end of the code (if !SECTION_BSS) | |
277 s -> codesize = CURBYTE() << 8; | |
278 NEXTBYTE(); | |
279 s -> codesize |= CURBYTE(); | |
280 NEXTBYTE(); | |
281 | |
282 s -> code = &(CURBYTE()); | |
283 | |
284 // skip the code if we're not in a BSS section | |
285 if (!(s -> flags & SECTION_BSS)) | |
286 { | |
287 int i; | |
288 for (i = 0; i < s -> codesize; i++) | |
289 NEXTBYTE(); | |
290 } | |
291 } | |
292 } |