coff32write.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
coff32write.c (9373B)
---
1 #include <assert.h>
2 #include <limits.h>
3 #include <stdint.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include <scc/mach.h>
9 #include <scc/coff32.h>
10
11 #include "../libmach.h"
12 #include "fun.h"
13
14 struct strtbl {
15 char *s;
16 long siz;
17 };
18
19 static void
20 pack_hdr(int order, unsigned char *buf, FILHDR *hdr)
21 {
22 int n;
23
24 n = pack(order,
25 buf,
26 "sslllss",
27 hdr->f_magic,
28 hdr->f_nscns,
29 hdr->f_timdat,
30 hdr->f_symptr,
31 hdr->f_nsyms,
32 hdr->f_opthdr,
33 hdr->f_flags);
34 assert(n == FILHSZ);
35 }
36
37 static void
38 pack_scn(int order, unsigned char *buf, SCNHDR *scn)
39 {
40 int n;
41
42 if (scn->s_zeroes == 0)
43 pack(order, buf, "ll", scn->s_zeroes, scn->s_offset);
44 else
45 memcpy(buf, scn->s_name, 8);
46
47 n = pack(order,
48 buf + 8,
49 "llllllssl",
50 scn->s_paddr,
51 scn->s_vaddr,
52 scn->s_size,
53 scn->s_scnptr,
54 scn->s_relptr,
55 scn->s_lnnoptr,
56 scn->s_nrelloc,
57 scn->s_nlnno,
58 scn->s_flags);
59 n += 8;
60 assert(n == SCNHSZ);
61 }
62
63 static void
64 pack_ent(int order, unsigned char *buf, SYMENT *ent)
65 {
66 int n;
67
68 if (ent->n_zeroes == 0)
69 pack(order, buf, "ll", ent->n_zeroes, ent->n_offset);
70 else
71 memcpy(buf, ent->n_name, 8);
72
73 n = pack(order,
74 buf + 8,
75 "lsscc",
76 ent->n_value,
77 ent->n_scnum,
78 ent->n_type,
79 ent->n_sclass,
80 ent->n_numaux);
81 n += 8;
82
83 assert(n == SYMESZ);
84 }
85
86 static void
87 pack_aux_file(int order, unsigned char *buf, AUXENT *aux)
88 {
89
90 if (aux->x_zeroes == 0) {
91 memset(buf, 0, sizeof(AUXESZ));
92 pack(order, buf, "ll", aux->x_zeroes, aux->x_offset);
93 } else {
94 memcpy(buf, aux->x_fname, E_FILNMLEN);
95 }
96 }
97
98 static void
99 pack_aux_scn(int order, unsigned char *buf, AUXENT *aux)
100 {
101 int n;
102
103 n = pack(order,
104 buf,
105 "lsslsc",
106 aux->x_scnlen,
107 aux->x_nreloc,
108 aux->x_nlinno,
109 aux->x_checksum,
110 aux->x_associated,
111 aux->x_comdat);
112 assert(n == AUXESZ);
113 }
114
115 static void
116 pack_aux_fun(int order, unsigned char *buf, AUXENT *aux)
117 {
118 int n;
119
120 n = pack(order,
121 buf,
122 "lllls",
123 aux->x_tagndx,
124 aux->x_fsize,
125 aux->x_lnnoptr,
126 aux->x_endndx,
127 aux->x_tvndx);
128 assert(n == AUXESZ);
129 }
130
131 static void
132 pack_aux_ary(int order, unsigned char *buf, AUXENT *aux)
133 {
134 int n;
135
136 n = pack(order,
137 buf,
138 "lssssss",
139 aux->x_tagndx,
140 aux->x_lnno,
141 aux->x_size,
142 aux->x_dimen[0],
143 aux->x_dimen[1],
144 aux->x_dimen[2],
145 aux->x_dimen[3],
146 aux->x_tvndx);
147 assert(n == AUXESZ);
148 }
149
150 static void
151 pack_aux_sym(int order, unsigned char *buf, AUXENT *aux)
152 {
153 int n;
154
155 n = pack(order,
156 buf,
157 "lsslls",
158 aux->x_tagndx,
159 aux->x_lnno,
160 aux->x_size,
161 aux->x_lnnoptr,
162 aux->x_endndx,
163 aux->x_tvndx);
164 assert(n == AUXESZ);
165 }
166
167 static void
168 pack_aout(int order, unsigned char *buf, AOUTHDR *aout)
169 {
170 int n;
171
172 n = pack(order,
173 buf,
174 "ssllllll",
175 aout->magic,
176 aout->vstamp,
177 aout->tsize,
178 aout->dsize,
179 aout->bsize,
180 aout->entry,
181 aout->text_start,
182 aout->data_start);
183 assert(n == AOUTSZ);
184 }
185
186 static void
187 pack_reloc(int order, unsigned char *buf, RELOC *rel)
188 {
189 int n;
190
191 n = pack(order,
192 buf,
193 "lls",
194 rel->r_vaddr,
195 rel->r_symndx,
196 rel->r_type);
197 assert(n == RELSZ);
198 }
199
200 static void
201 pack_line(int order, unsigned char *buf, LINENO *lp)
202 {
203 int n;
204
205 n = pack(order,
206 buf,
207 "lls",
208 lp->l_addr.l_symndx,
209 lp->l_lnno);
210 assert(n == LINESZ);
211 }
212
213 static int
214 writehdr(Obj *obj, FILE *fp)
215 {
216 FILHDR *hdr;
217 struct coff32 *coff;
218 unsigned char buf[FILHSZ];
219
220 coff = obj->data;
221 hdr = &coff->hdr;
222
223 pack_hdr(ORDER(obj->type), buf, hdr);
224 if (fwrite(buf, FILHSZ, 1, fp) != 1)
225 return 0;
226
227 return 1;
228 }
229
230 static int
231 allocstring(struct coff32 *coff, long off, struct strtbl *tbl)
232 {
233 char *s, *name;
234 long len, siz;
235
236 siz = tbl->siz;
237 name = &coff->strtbl[off];
238 len = strlen(name) + 1;
239 if (len > siz - LONG_MAX)
240 return 0;
241
242 s = realloc(tbl->s, siz + len);
243 if (!s)
244 return 0;
245 memcpy(s + siz, name, len);
246
247 tbl->s = s;
248 tbl->siz += len;
249
250 return 1;
251 }
252
253 static int
254 writescns(Obj *obj, FILE *fp, struct strtbl *tbl)
255 {
256 int i;
257 SCNHDR *scn;
258 FILHDR *hdr;
259 struct coff32 *coff;
260 unsigned char buf[SCNHSZ];
261
262 coff = obj->data;
263 hdr = &coff->hdr;
264
265 for (i = 0; i < hdr->f_nscns; i++) {
266 scn = &coff->scns[i];
267 if (scn->s_zeroes == 0) {
268 if (!allocstring(coff, scn->s_offset, tbl))
269 return 0;
270 }
271 pack_scn(ORDER(obj->type), buf, scn);
272 if (fwrite(buf, SCNHSZ, 1, fp) != 1)
273 return 0;
274 }
275
276 return 1;
277 }
278
279 static int
280 writeents(Obj *obj, FILE *fp, struct strtbl *tbl)
281 {
282 long i;
283 FILHDR *hdr;
284 struct coff32 *coff;
285 unsigned char buf[SYMESZ];
286
287 coff = obj->data;
288 hdr = &coff->hdr;
289
290 if (!coff->ents)
291 return 1;
292
293 for (i = 0; i < hdr->f_nsyms; i++) {
294 SYMENT *ent;
295 AUXENT *aux;
296 Entry *ep = &coff->ents[i];
297
298 aux = &ep->u.aux;
299 switch (ep->type) {
300 case SYM_ENT:
301 ent = &ep->u.sym;
302 if (ent->n_zeroes == 0) {
303 if (!allocstring(coff, ent->n_offset, tbl))
304 return 0;
305 }
306 pack_ent(ORDER(obj->type), buf, ent);
307 break;
308 case SYM_AUX_UNK:
309 memcpy(buf, ep->u.buf, AUXESZ);
310 break;
311 case SYM_AUX_SYM:
312 pack_aux_file(ORDER(obj->type), buf, aux);
313 break;
314 case SYM_AUX_FILE:
315 if (aux->x_zeroes == 0) {
316 if (!allocstring(coff, aux->x_offset, tbl))
317 return 0;
318 }
319 pack_aux_file(ORDER(obj->type), buf, aux);
320 break;
321 case SYM_AUX_SCN:
322 pack_aux_scn(ORDER(obj->type), buf, aux);
323 break;
324 case SYM_AUX_FUN:
325 pack_aux_fun(ORDER(obj->type), buf, aux);
326 break;
327 case SYM_AUX_ARY:
328 pack_aux_ary(ORDER(obj->type), buf, aux);
329 break;
330 }
331
332 if (fwrite(buf, SYMESZ, 1, fp) != 1)
333 return 0;
334 }
335
336 return 1;
337 }
338
339 static int
340 writestr(Obj *obj, FILE *fp, struct strtbl *tbl)
341 {
342 struct coff32 *coff;
343 unsigned char buf[4];
344
345 coff = obj->data;
346
347 free(coff->strtbl);
348 coff->strtbl = tbl->s;
349 coff->strsiz = tbl->siz;
350 tbl->s = NULL;
351 tbl->siz = 0;
352
353 if ((coff->strsiz & 0xffff) != coff->strsiz)
354 return 0;
355
356 pack(ORDER(obj->type), buf, "l", coff->strsiz);
357 fwrite(buf, 4, 1, fp);
358 fwrite(coff->strtbl, coff->strsiz, 1, fp);
359
360 return 1;
361 }
362
363 static int
364 writeaout(Obj *obj, FILE *fp)
365 {
366 FILHDR *hdr;
367 struct coff32 *coff;
368 unsigned char buf[AOUTSZ];
369
370 coff = obj->data;
371 hdr = &coff->hdr;
372
373 if (hdr->f_opthdr == 0)
374 return 1;
375 pack_aout(ORDER(obj->type), buf, &coff->aout);
376
377 return fread(buf, AOUTSZ, 1, fp) != 1;
378 }
379
380 static int
381 writereloc(Obj *obj, FILE *fp)
382 {
383 int i, j;
384 RELOC *rp;
385 SCNHDR *scn;
386 FILHDR *hdr;
387 struct coff32 *coff;
388 unsigned char buf[RELSZ];
389
390 coff = obj->data;
391 hdr = &coff->hdr;
392
393 if (!coff->rels)
394 return 1;
395
396 for (i = 0; i < hdr->f_nscns; i++) {
397 rp = coff->rels[i];
398 if (!rp)
399 continue;
400 scn = &coff->scns[i];
401
402 for (j = 0; j < scn->s_nrelloc; j++) {
403 pack_reloc(ORDER(obj->type), buf, &rp[i]);
404 if (fwrite(buf, RELSZ, 1, fp) != 1)
405 return 0;
406 }
407 }
408
409 return 1;
410 }
411
412 static int
413 writelines(Obj *obj, FILE *fp)
414 {
415 int i;
416 long j;
417 LINENO *lp;
418 SCNHDR *scn;
419 struct coff32 *coff = obj->data;
420 FILHDR *hdr = &coff->hdr;
421 unsigned char buf[LINESZ];
422
423 if (!coff->lines)
424 return 1;
425
426 for (i = 0; i < hdr->f_nscns; i++) {
427 lp = coff->lines[i];
428 if (!lp)
429 continue;
430 scn = &coff->scns[i];
431 for (j = 0; j < scn->s_nlnno; j++) {
432 pack_line(ORDER(obj->type), buf, &lp[j]);
433 if (fwrite(buf, LINESZ, 1, fp) == 1)
434 return 0;
435 }
436 }
437
438 return 1;
439 }
440
441 static int
442 writedata(Obj *obj, Map *map, FILE *fp)
443 {
444 long n;
445 int id, nsec;
446 Mapsec *msec;
447 Section *sec;
448 struct coff32 *coff = obj->data;
449 FILHDR *hdr = &coff->hdr;
450 SCNHDR *scn;
451
452 nsec = hdr->f_nscns;
453 for (scn = coff->scns; nsec--; scn++) {
454 if ((id = findsec(map, scn->s_name)) < 0)
455 continue;
456 msec = &map->sec[id];
457 sec = &msec->sec;
458 if (!msec->fp)
459 continue;
460
461 if (copysec(msec, fp) < 0)
462 return -1;
463 }
464
465 return 1;
466 }
467
468 int
469 coff32write(Obj *obj, Map *map, FILE *fp)
470 {
471 int id;
472 long ptr, n;
473 SCNHDR *scn;
474 Mapsec *sec;
475 struct strtbl tbl;
476 struct coff32 *coff = obj->data;
477 FILHDR *hdr = &coff->hdr;
478
479 ptr = ftell(fp);
480 obj->pos = ptr;
481 tbl.s = NULL;
482 tbl.siz = 0;
483
484 n = hdr->f_nscns;
485 ptr += FILHSZ + hdr->f_opthdr + n*SCNHSZ;
486 for (scn = coff->scns; n--; scn++) {
487 scn->s_scnptr = 0;
488 if ((id = findsec(map, scn->s_name)) < 0)
489 continue;
490 sec = &map->sec[id];
491 if (!sec->fp)
492 continue;
493
494 scn->s_scnptr = ptr;
495 ptr += scn->s_size;
496 }
497 hdr->f_symptr = (hdr->f_nsyms > 0) ? ptr : 0;
498
499 n = hdr->f_nscns;
500 for (scn = coff->scns; n--; scn++) {
501 scn->s_relptr = (scn->s_nrelloc > 0) ? ptr : 0;
502 ptr += scn->s_nrelloc * RELSZ;
503 }
504
505 n = hdr->f_nscns;
506 for (scn = coff->scns; n--; scn++) {
507 scn->s_lnnoptr = (scn->s_nlnno > 0) ? ptr : 0;
508 ptr += scn->s_nlnno * RELSZ;
509 }
510
511 /* and now update symbols */
512
513 if (!writehdr(obj, fp))
514 goto err;
515 if (!writeaout(obj, fp))
516 goto err;
517 if (!writescns(obj, fp, &tbl))
518 goto err;
519 if (!writedata(obj, map, fp))
520 goto err;
521 if (!writereloc(obj, fp))
522 goto err;
523 if (!writelines(obj, fp))
524 goto err;
525 if (!writeents(obj, fp, &tbl))
526 goto err;
527 if (!writestr(obj, fp, &tbl))
528 goto err;
529 if (ferror(fp))
530 goto err;
531 return 0;
532
533 err:
534 free(tbl.s);
535 return -1;
536 }