comparison lwasm/section.c @ 0:2c24602be78f

Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
author lost@l-w.ca
date Wed, 19 Jan 2011 22:27:17 -0700
parents
children 7317fbe024af
comparison
equal deleted inserted replaced
-1:000000000000 0:2c24602be78f
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 <string.h>
23
24 #include <lw_string.h>
25 #include <lw_alloc.h>
26
27 #include "lwasm.h"
28 #include "instab.h"
29
30 PARSEFUNC(pseudo_parse_section)
31 {
32 char *p2;
33 char *sn;
34 char *opts = NULL;
35 sectiontab_t *s;
36
37 if (as -> output_format != OUTPUT_OBJ)
38 {
39 lwasm_register_error(as, l, "Cannot use sections unless using the object target");
40 return;
41 }
42
43 if (!**p)
44 {
45 lwasm_register_error(as, l, "Need section name");
46 return;
47 }
48
49 l -> len = 0;
50
51 if (as -> csect)
52 {
53 lw_expr_destroy(as -> csect -> offset);
54 as -> csect -> offset = lw_expr_copy(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 -> oblen = 0;
90 s -> obsize = 0;
91 s -> obytes = NULL;
92 s -> name = lw_strdup(sn);
93 s -> offset = lw_expr_build(lw_expr_type_special, lwasm_expr_secbase, s);
94 s -> flags = section_flag_none;
95 s -> reloctab = NULL;
96 if (!strcasecmp(sn, "bss") || !strcasecmp(sn, ".bss"))
97 {
98 s -> flags |= section_flag_bss;
99 }
100 // parse options
101 if (opts)
102 {
103 // only one option ("bss" or "!bss")
104 if (!strcasecmp(opts, "bss"))
105 {
106 s -> flags |= section_flag_bss;
107 }
108 else if (!strcasecmp(opts, "!bss"))
109 {
110 s -> flags &= ~section_flag_bss;
111 }
112 else
113 {
114 lwasm_register_error(as, l, "Unrecognized section flag");
115 lw_free(sn);
116 lw_free(opts);
117 lw_free(s -> name);
118 lw_expr_destroy(s -> offset);
119 lw_free(s);
120 return;
121 }
122 }
123 s -> next = as -> sections;
124 as -> sections = s;
125 }
126
127 lw_expr_destroy(l -> addr);
128 l -> addr = lw_expr_copy(s -> offset);
129
130 as -> csect = s;
131 as -> context = lwasm_next_context(as);
132
133 l -> len = 0;
134
135 lw_free(opts);
136 lw_free(sn);
137 }
138
139 PARSEFUNC(pseudo_parse_endsection)
140 {
141 if (as -> output_format != OUTPUT_OBJ)
142 {
143 lwasm_register_error(as, l, "Cannot use sections unless using the object target");
144 return;
145 }
146
147 l -> len = 0;
148
149 if (!(as -> csect))
150 {
151 lwasm_register_error(as, l, "ENDSECTION without SECTION");
152 return;
153 }
154
155 // save offset in case another instance of the section appears
156 lw_expr_destroy(as -> csect -> offset);
157 as -> csect -> offset = l -> addr;
158
159 // reset address to 0
160 l -> addr = lw_expr_build(lw_expr_type_int, 0);
161 as -> csect = NULL;
162
163 // end of section is a context break
164 as -> context = lwasm_next_context(as);
165
166 skip_operand(p);
167 }
168
169 PARSEFUNC(pseudo_parse_export)
170 {
171 int after = 0;
172 char *sym = NULL;
173 exportlist_t *e;
174
175 if (as -> output_format != OUTPUT_OBJ)
176 {
177 lwasm_register_error(as, l, "EXPORT only supported for object target");
178 return;
179 }
180
181 l -> len = 0;
182
183 if (l -> sym)
184 {
185 sym = lw_strdup(l -> sym);
186 l -> symset = 1;
187 }
188
189 if (l -> sym)
190 {
191 skip_operand(p);
192 }
193
194 again:
195 if (after || !sym)
196 {
197 char *p2;
198
199 after = 1;
200 for (p2 = *p; *p2 && *p2 != ',' && !isspace(*p2); p2++)
201 /* do nothing */ ;
202
203 sym = lw_strndup(*p, p2 - *p);
204 *p = p2;
205 }
206 if (!sym)
207 {
208 lwasm_register_error(as, l, "No symbol for EXPORT");
209 return;
210 }
211
212 // add the symbol to the "export" list (which will be resolved
213 // after the parse pass is complete
214 e = lw_alloc(sizeof(exportlist_t));
215 e -> next = as -> exportlist;
216 e -> symbol = lw_strdup(sym);
217 e -> line = l;
218 e -> se = NULL;
219 as -> exportlist = e;
220 lw_free(sym);
221
222 if (after && **p == ',')
223 {
224 (*p)++;
225 for (; **p && isspace(**p); (*p)++)
226 /* do nothing */ ;
227 goto again;
228 }
229 }
230
231 PARSEFUNC(pseudo_parse_extern)
232 {
233 int after = 0;
234 char *sym = NULL;
235 importlist_t *e;
236
237 if (as -> output_format != OUTPUT_OBJ)
238 {
239 lwasm_register_error(as, l, "IMPORT only supported for object target");
240 return;
241 }
242
243 l -> len = 0;
244
245 if (l -> sym)
246 {
247 sym = lw_strdup(l -> sym);
248 l -> symset = 1;
249 }
250
251 if (l -> sym)
252 {
253 skip_operand(p);
254 }
255
256 again:
257 if (after || !sym)
258 {
259 char *p2;
260
261 after = 1;
262 for (p2 = *p; *p2 && *p2 != ',' && !isspace(*p2); p2++)
263 /* do nothing */ ;
264
265 sym = lw_strndup(*p, p2 - *p);
266 *p = p2;
267 }
268 if (!sym)
269 {
270 lwasm_register_error(as, l, "No symbol for IMPORT");
271 return;
272 }
273
274 // add the symbol to the "export" list (which will be resolved
275 // after the parse pass is complete
276 e = lw_alloc(sizeof(importlist_t));
277 e -> next = as -> importlist;
278 e -> symbol = lw_strdup(sym);
279 as -> importlist = e;
280 lw_free(sym);
281
282 if (after && **p == ',')
283 {
284 (*p)++;
285 for (; **p && isspace(**p); (*p)++)
286 /* do nothing */ ;
287 goto again;
288 }
289 }
290
291 PARSEFUNC(pseudo_parse_extdep)
292 {
293 int after = 0;
294 char *sym = NULL;
295 importlist_t *e;
296
297 if (as -> output_format != OUTPUT_OBJ)
298 {
299 lwasm_register_error(as, l, "EXTDEP only supported for object target");
300 return;
301 }
302
303 if (!as -> csect)
304 {
305 lwasm_register_error(as, l, "EXTDEP must be within a section");
306 return;
307 }
308
309 l -> len = 0;
310
311 if (l -> sym)
312 sym = lw_strdup(l -> sym);
313
314 if (l -> sym)
315 {
316 skip_operand(p);
317 }
318
319 again:
320 if (after || !sym)
321 {
322 char *p2;
323
324 after = 1;
325 for (p2 = *p; *p2 && *p2 != ',' && !isspace(*p2); p2++)
326 /* do nothing */ ;
327
328 sym = lw_strndup(*p, p2 - *p);
329 }
330 if (!sym)
331 {
332 lwasm_register_error(as, l, "No symbol for EXTDEP");
333 return;
334 }
335
336 // create a zero-width dependency
337 {
338 lw_expr_t e;
339 e = lw_expr_build(lw_expr_type_int, 0);
340 lwasm_emitexpr(l, e, 0);
341 lw_expr_destroy(e);
342 }
343
344 if (after && **p == ',')
345 {
346 (*p)++;
347 for (; **p && isspace(**p); (*p)++)
348 /* do nothing */ ;
349 goto again;
350 }
351 }