coff32setsec.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
---
coff32setsec.c (2354B)
---
1 #include <limits.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include <scc/mach.h>
7 #include <scc/coff32.h>
8
9 #include "../libmach.h"
10 #include "fun.h"
11
12 static char *
13 secname(Coff32 *coff, SCNHDR *scn, Section *sec)
14 {
15 char *p;
16 unsigned long siz = strlen(sec->name);
17
18 if (siz < SCNNMLEN)
19 return strncpy(scn->s_name, sec->name, SCNNMLEN);
20
21 if (coff->strsiz > ULONG_MAX - siz - 1)
22 return NULL;
23
24 siz += coff->strsiz + 1;
25 if ((p = realloc(coff->strtbl, siz)) == NULL)
26 return NULL;
27 coff->strtbl = p;
28
29 scn->s_zeroes = 0;
30 scn->s_offset = coff->strsiz;
31 coff->strsiz += siz;
32 return strcpy(&coff->strtbl[scn->s_offset], sec->name);
33 }
34
35 Section *
36 coff32setsec(Obj *obj, int *idx, Section *sec)
37 {
38 long flags, n = *idx;
39 SCNHDR *scn;
40 Coff32 *coff = obj->data;
41 FILHDR *hdr = &coff->hdr;
42
43 /* TODO: what happens with SABS? */
44 switch (sec->type) {
45 case 'D':
46 switch (sec->flags) {
47 case SALLOC | SRELOC | SLOAD | SWRITE | SREAD:
48 if (strcmp(sec->name ,".data") == 0)
49 flags = STYP_DATA;
50 else
51 flags = STYP_REG;
52 break;
53 case SALLOC | SREAD | SWRITE:
54 flags = STYP_NOLOAD;
55 break;
56 case SALLOC | SRELOC | SLOAD | SREAD:
57 flags = STYP_RDATA;
58 break;
59 case SEXEC | SALLOC | SRELOC | SLOAD | SREAD:
60 flags = STYP_TEXT | STYP_DATA;
61 break;
62 default:
63 goto invalid;
64 }
65 break;
66 case 'T':
67 flags = STYP_TEXT;
68 break;
69 case 'B':
70 flags = STYP_BSS;
71 break;
72 case 'N':
73 case '?':
74 default:
75 invalid:
76 /* TODO */
77 return NULL;
78 }
79
80 if (strlen(sec->name) >= SCNNMLEN)
81 return NULL;
82
83 if (n >= hdr->f_nscns) {
84 if (n > SHRT_MAX - 1)
85 return NULL;
86 scn = realloc(coff->scns, (n+1) * sizeof(SCNHDR));
87 if (!scn)
88 return NULL;
89 coff->scns = scn;
90 hdr->f_nscns = n + 1;
91 }
92
93 scn = &coff->scns[n];
94 if (!secname(coff, scn, sec))
95 return NULL;
96
97 /*
98 * sec->offset is ignored because it is very unlikely
99 * that the vaule is meaningful here. The field offset
100 * was added only to allow getsec to retrive the information
101 * in a generic way, but it was never expected to be a 2 way
102 * relation. That pointer is updated when the object file
103 * is written using a mapping.
104 */
105 scn->s_paddr = sec->load;
106 scn->s_vaddr = sec->base;
107 scn->s_size = sec->size;
108 scn->s_scnptr = 0;
109 scn->s_relptr = 0;
110 scn->s_lnnoptr = 0;
111 scn->s_nrelloc = 0;
112 scn->s_nlnno = 0;
113 scn->s_flags = flags;
114
115 return sec;
116 }