353
|
1 /*
|
|
2 section.c
|
|
3
|
|
4 Copyright © 2010 William Astle
|
|
5
|
|
6 This file is part of LWTOOLS.
|
|
7
|
|
8 LWTOOLS is free software: you can redistribute it and/or modify it under the
|
|
9 terms of the GNU General Public License as published by the Free Software
|
|
10 Foundation, either version 3 of the License, or (at your option) any later
|
|
11 version.
|
|
12
|
|
13 This program is distributed in the hope that it will be useful, but WITHOUT
|
|
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
16 more details.
|
|
17
|
|
18 You should have received a copy of the GNU General Public License along with
|
|
19 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20 */
|
|
21
|
|
22 #include <config.h>
|
|
23
|
|
24 #include <string.h>
|
|
25
|
|
26 #include <lw_string.h>
|
|
27 #include <lw_alloc.h>
|
|
28
|
|
29 #include "lwasm.h"
|
|
30 #include "instab.h"
|
|
31
|
|
32 PARSEFUNC(pseudo_parse_section)
|
|
33 {
|
|
34 char *p2;
|
|
35 char *sn;
|
|
36 char *opts = NULL;
|
|
37 sectiontab_t *s;
|
|
38
|
|
39 if (as -> output_format != OUTPUT_OBJ)
|
|
40 {
|
|
41 lwasm_register_error(as, l, "Cannot use sections unless using the object target");
|
|
42 return;
|
|
43 }
|
|
44
|
|
45 if (!**p)
|
|
46 {
|
|
47 lwasm_register_error(as, l, "Need section name");
|
|
48 return;
|
|
49 }
|
|
50
|
|
51 if (as -> csect)
|
|
52 {
|
|
53 lw_expr_destroy(as -> csect -> offset);
|
|
54 as -> csect -> offset = l -> addr;
|
|
55 as -> csect = NULL;
|
|
56 }
|
|
57
|
|
58 for (p2 = *p; *p2 && *p2 != ',' && !isspace(*p2); p2++)
|
|
59 /* do nothing */ ;
|
|
60
|
|
61 sn = lw_strndup(*p, p2 - *p);
|
|
62 *p = p2;
|
|
63
|
|
64 if (**p == ',')
|
|
65 {
|
|
66 // have opts
|
|
67 (*p)++;
|
|
68
|
|
69 for (p2 = *p; *p2 && !isspace(*p2); p2++)
|
|
70 /* do nothing */ ;
|
|
71
|
|
72 opts = lw_strndup(*p, p2 - *p);
|
|
73 *p = p2;
|
|
74 }
|
|
75
|
|
76 for (s = as -> sections; s; s = s -> next)
|
|
77 {
|
|
78 if (!strcmp(s -> name, sn))
|
|
79 break;
|
|
80 }
|
|
81 if (s && opts)
|
|
82 {
|
|
83 lwasm_register_warning(as, l, "Section flags can only be specified the first time; ignoring duplicate definition");
|
|
84 }
|
|
85 if (!s)
|
|
86 {
|
|
87 // create section data structure
|
|
88 s = lw_alloc(sizeof(sectiontab_t));
|
|
89 s -> name = lw_strdup(sn);
|
|
90 s -> offset = lw_expr_build(lw_expr_type_int, 0);
|
|
91 s -> flags = section_flag_none;
|
|
92 if (!strcasecmp(sn, "bss") || !strcasecmp(sn, ".bss"))
|
|
93 {
|
|
94 s -> flags |= section_flag_bss;
|
|
95 }
|
|
96 // parse options
|
|
97 if (opts)
|
|
98 {
|
|
99 // only one option ("bss" or "!bss")
|
|
100 if (!strcasecmp(opts, "bss"))
|
|
101 {
|
|
102 s -> flags |= section_flag_bss;
|
|
103 }
|
|
104 else if (!strcasecmp(opts, "!bss"))
|
|
105 {
|
|
106 s -> flags &= ~section_flag_bss;
|
|
107 }
|
|
108 else
|
|
109 {
|
|
110 lwasm_register_error(as, l, "Unrecognized section flag");
|
|
111 lw_free(sn);
|
|
112 lw_free(opts);
|
|
113 lw_free(s -> name);
|
|
114 lw_expr_destroy(s -> offset);
|
|
115 lw_free(s);
|
|
116 return;
|
|
117 }
|
|
118 }
|
|
119 s -> next = as -> sections;
|
|
120 as -> sections = s;
|
|
121 }
|
|
122
|
|
123 lw_expr_destroy(l -> addr);
|
|
124 l -> addr = lw_expr_copy(s -> offset);
|
|
125
|
|
126 as -> csect = s;
|
|
127 as -> context = lwasm_next_context(as);
|
|
128
|
|
129 l -> len = 0;
|
|
130
|
|
131 lw_free(opts);
|
|
132 lw_free(sn);
|
|
133 }
|
|
134
|
|
135 PARSEFUNC(pseudo_parse_endsection)
|
|
136 {
|
|
137 if (as -> output_format != OUTPUT_OBJ)
|
|
138 {
|
|
139 lwasm_register_error(as, l, "Cannot use sections unless using the object target");
|
|
140 return;
|
|
141 }
|
|
142
|
|
143 if (!(as -> csect))
|
|
144 {
|
|
145 lwasm_register_error(as, l, "ENDSECTION without SECTION");
|
|
146 return;
|
|
147 }
|
|
148
|
|
149 // save offset in case another instance of the section appears
|
|
150 lw_expr_destroy(as -> csect -> offset);
|
|
151 as -> csect -> offset = l -> addr;
|
|
152
|
|
153 // reset address to 0
|
|
154 l -> addr = lw_expr_build(lw_expr_type_int, 0);
|
|
155 as -> csect = NULL;
|
|
156
|
|
157 // end of section is a context break
|
|
158 as -> context = lwasm_next_context(as);
|
|
159
|
|
160 skip_operand(p);
|
|
161 }
|
356
|
162
|
|
163 PARSEFUNC(pseudo_parse_export)
|
|
164 {
|
|
165 int after = 0;
|
|
166 char *sym = NULL;
|
|
167 exportlist_t *e;
|
|
168
|
|
169 if (as -> output_format != OUTPUT_OBJ)
|
|
170 {
|
|
171 lwasm_register_error(as, l, "EXPORT only supported for object target");
|
|
172 return;
|
|
173 }
|
|
174
|
|
175 if (l -> sym)
|
|
176 sym = lw_strdup(l -> sym);
|
|
177
|
|
178 if (l -> sym)
|
|
179 {
|
|
180 skip_operand(p);
|
|
181 }
|
|
182
|
|
183 again:
|
|
184 if (after || !sym)
|
|
185 {
|
|
186 char *p2;
|
|
187
|
|
188 after = 1;
|
|
189 for (p2 = *p; *p2 && *p2 != ',' && !isspace(*p2); p2++)
|
|
190 /* do nothing */ ;
|
|
191
|
|
192 sym = lw_strndup(*p, p2 - *p);
|
|
193 }
|
|
194 if (!sym)
|
|
195 {
|
|
196 lwasm_register_error(as, l, "No symbol for EXPORT");
|
|
197 return;
|
|
198 }
|
|
199
|
|
200 // add the symbol to the "export" list (which will be resolved
|
|
201 // after the parse pass is complete
|
|
202 e = lw_alloc(sizeof(exportlist_t));
|
|
203 e -> next = as -> exportlist;
|
|
204 e -> symbol = lw_strdup(sym);
|
|
205 as -> exportlist = e;
|
|
206 lw_free(sym);
|
|
207
|
|
208 if (after && **p == ',')
|
|
209 {
|
|
210 (*p)++;
|
|
211 for (; **p && isspace(**p); (*p)++)
|
|
212 /* do nothing */ ;
|
|
213 goto again;
|
|
214 }
|
|
215 }
|
|
216
|
|
217 PARSEFUNC(pseudo_parse_extern)
|
|
218 {
|
|
219 int after = 0;
|
|
220 char *sym = NULL;
|
|
221 importlist_t *e;
|
|
222
|
|
223 if (as -> output_format != OUTPUT_OBJ)
|
|
224 {
|
|
225 lwasm_register_error(as, l, "IMPORT only supported for object target");
|
|
226 return;
|
|
227 }
|
|
228
|
|
229 if (l -> sym)
|
|
230 sym = lw_strdup(l -> sym);
|
|
231
|
|
232 if (l -> sym)
|
|
233 {
|
|
234 skip_operand(p);
|
|
235 }
|
|
236
|
|
237 again:
|
|
238 if (after || !sym)
|
|
239 {
|
|
240 char *p2;
|
|
241
|
|
242 after = 1;
|
|
243 for (p2 = *p; *p2 && *p2 != ',' && !isspace(*p2); p2++)
|
|
244 /* do nothing */ ;
|
|
245
|
|
246 sym = lw_strndup(*p, p2 - *p);
|
|
247 }
|
|
248 if (!sym)
|
|
249 {
|
|
250 lwasm_register_error(as, l, "No symbol for IMPORT");
|
|
251 return;
|
|
252 }
|
|
253
|
|
254 // add the symbol to the "export" list (which will be resolved
|
|
255 // after the parse pass is complete
|
|
256 e = lw_alloc(sizeof(importlist_t));
|
|
257 e -> next = as -> importlist;
|
|
258 e -> symbol = lw_strdup(sym);
|
|
259 as -> importlist = e;
|
|
260 lw_free(sym);
|
|
261
|
|
262 if (after && **p == ',')
|
|
263 {
|
|
264 (*p)++;
|
|
265 for (; **p && isspace(**p); (*p)++)
|
|
266 /* do nothing */ ;
|
|
267 goto again;
|
|
268 }
|
|
269 }
|