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 }
|