Mercurial > hg > index.cgi
comparison lwlink/script.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 script.c | |
3 Copyright © 2009 William Astle | |
4 | |
5 This file is part of LWLINK. | |
6 | |
7 LWLINK is free software: you can redistribute it and/or modify it under the | |
8 terms of the GNU General Public License as published by the Free Software | |
9 Foundation, either version 3 of the License, or (at your option) any later | |
10 version. | |
11 | |
12 This program is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
15 more details. | |
16 | |
17 You should have received a copy of the GNU General Public License along with | |
18 this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 | |
21 Read and parse linker scripts | |
22 */ | |
23 | |
24 #include <errno.h> | |
25 #include <stdio.h> | |
26 #include <stdlib.h> | |
27 #include <string.h> | |
28 | |
29 #include "lwlink.h" | |
30 #include "util.h" | |
31 | |
32 // the built-in DECB target linker script | |
33 static char *decb_script = | |
34 "section init load 2000\n" | |
35 "section code\n" | |
36 "section *,!bss\n" | |
37 "section *,bss\n" | |
38 "entry 2000\n" | |
39 ; | |
40 | |
41 // the built-in RAW target linker script | |
42 static char *raw_script = | |
43 "section init load 0000\n" | |
44 "section code\n" | |
45 "section *,!bss\n" | |
46 "section *,bss\n" | |
47 ; | |
48 | |
49 static char *lwex0_script = | |
50 "section init load 0100\n" | |
51 "section .text\n" | |
52 "section .data\n" | |
53 "section *,!bss\n" | |
54 "section *,bss\n" | |
55 "entry __start\n" | |
56 "stacksize 0100\n" // default 256 byte stack | |
57 ; | |
58 | |
59 // the "simple" script | |
60 static char *simple_script = | |
61 "section *,!bss\n" | |
62 "section *,bss\n" | |
63 ; | |
64 | |
65 linkscript_t linkscript = { 0, NULL, -1 }; | |
66 | |
67 void setup_script() | |
68 { | |
69 char *script, *oscript; | |
70 long size; | |
71 | |
72 // read the file if needed | |
73 if (scriptfile) | |
74 { | |
75 FILE *f; | |
76 long bread; | |
77 | |
78 f = fopen(scriptfile, "rb"); | |
79 if (!f) | |
80 { | |
81 fprintf(stderr, "Can't open file %s:", scriptfile); | |
82 perror(""); | |
83 exit(1); | |
84 } | |
85 fseek(f, 0, SEEK_END); | |
86 size = ftell(f); | |
87 rewind(f); | |
88 | |
89 script = lw_malloc(size + 2); | |
90 | |
91 bread = fread(script, 1, size, f); | |
92 if (bread < size) | |
93 { | |
94 fprintf(stderr, "Short read on file %s (%ld/%ld):", scriptfile, bread, size); | |
95 perror(""); | |
96 exit(1); | |
97 } | |
98 fclose(f); | |
99 | |
100 script[size] = '\n'; | |
101 script[size + 1] = '\0'; | |
102 } | |
103 else | |
104 { | |
105 // fetch defaults based on output mode | |
106 switch (outformat) | |
107 { | |
108 case OUTPUT_RAW: | |
109 script = raw_script; | |
110 break; | |
111 | |
112 case OUTPUT_DECB: | |
113 script = decb_script; | |
114 break; | |
115 | |
116 case OUTPUT_LWEX0: | |
117 script = lwex0_script; | |
118 break; | |
119 | |
120 default: | |
121 script = simple_script; | |
122 break; | |
123 } | |
124 | |
125 size = strlen(script); | |
126 if (nscriptls) | |
127 { | |
128 char *rscript; | |
129 int i; | |
130 // prepend the "extra" script lines | |
131 for (i = 0; i < nscriptls; i++) | |
132 size += strlen(scriptls[i]) + 1; | |
133 | |
134 rscript = lw_malloc(size + 1); | |
135 oscript = rscript; | |
136 for (i = 0; i < nscriptls; i++) | |
137 { | |
138 oscript += sprintf(oscript, "%s\n", scriptls[i]); | |
139 } | |
140 strcpy(oscript, script); | |
141 script = rscript; | |
142 } | |
143 } | |
144 | |
145 if (outformat == OUTPUT_LWEX0) | |
146 linkscript.stacksize = 0x100; | |
147 | |
148 oscript = script; | |
149 // now parse the script file | |
150 while (*script) | |
151 { | |
152 char *ptr, *ptr2, *line; | |
153 | |
154 for (ptr = script; *ptr && *ptr != '\n' && *ptr != '\r'; ptr++) | |
155 /* do nothing */ ; | |
156 | |
157 line = lw_malloc(ptr - script + 1); | |
158 memcpy(line, script, ptr - script); | |
159 line[ptr - script] = '\0'; | |
160 | |
161 // skip line terms | |
162 for (script = ptr + 1; *script == '\n' || *script == '\r'; script++) | |
163 /* do nothing */ ; | |
164 | |
165 // ignore leading whitespace | |
166 for (ptr = line; *ptr && isspace(*ptr); ptr++) | |
167 /* do nothing */ ; | |
168 | |
169 // ignore blank lines | |
170 if (!*ptr) | |
171 continue; | |
172 | |
173 for (ptr = line; *ptr && !isspace(*ptr); ptr++) | |
174 /* do nothing */ ; | |
175 | |
176 // now ptr points to the char past the first word | |
177 // NUL it out | |
178 if (*ptr) | |
179 *ptr++ = '\0'; | |
180 | |
181 // skip spaces after the first word | |
182 for ( ; *ptr && isspace(*ptr); ptr++) | |
183 /* do nothing */ ; | |
184 | |
185 if (!strcmp(line, "pad")) | |
186 { | |
187 // padding | |
188 // parse the hex number and stow it | |
189 linkscript.padsize = strtol(ptr, NULL, 16); | |
190 if (linkscript.padsize < 0) | |
191 linkscript.padsize = 0; | |
192 } | |
193 else if (!strcmp(line, "stacksize")) | |
194 { | |
195 // stack size for targets that support it | |
196 // parse the hex number and stow it | |
197 linkscript.padsize = strtol(ptr, NULL, 16); | |
198 if (linkscript.stacksize < 0) | |
199 linkscript.stacksize = 0x100; | |
200 } | |
201 else if (!strcmp(line, "entry")) | |
202 { | |
203 int eaddr; | |
204 | |
205 eaddr = strtol(ptr, &ptr2, 16); | |
206 if (*ptr2) | |
207 { | |
208 linkscript.execaddr = -1; | |
209 linkscript.execsym = lw_strdup(ptr); | |
210 } | |
211 else | |
212 { | |
213 linkscript.execaddr = eaddr; | |
214 linkscript.execsym = NULL; | |
215 } | |
216 } | |
217 else if (!strcmp(line, "section")) | |
218 { | |
219 // section | |
220 // parse out the section name and flags | |
221 for (ptr2 = ptr; *ptr2 && !isspace(*ptr2); ptr2++) | |
222 /* do nothing */ ; | |
223 | |
224 if (*ptr2) | |
225 *ptr2++ = '\0'; | |
226 | |
227 while (*ptr2 && isspace(*ptr2)) | |
228 ptr2++; | |
229 | |
230 // ptr now points to the section name and flags and ptr2 | |
231 // to the first non-space character following | |
232 | |
233 // then look for "load <addr>" clause | |
234 if (*ptr2) | |
235 { | |
236 if (!strncmp(ptr2, "load", 4)) | |
237 { | |
238 ptr2 += 4; | |
239 while (*ptr2 && isspace(*ptr2)) | |
240 ptr2++; | |
241 | |
242 } | |
243 else | |
244 { | |
245 fprintf(stderr, "%s: bad script\n", scriptfile); | |
246 exit(1); | |
247 } | |
248 } | |
249 | |
250 // now ptr2 points to the load address if there is one | |
251 // or NUL if not | |
252 linkscript.lines = lw_realloc(linkscript.lines, sizeof(struct scriptline_s) * (linkscript.nlines + 1)); | |
253 | |
254 linkscript.lines[linkscript.nlines].noflags = 0; | |
255 linkscript.lines[linkscript.nlines].yesflags = 0; | |
256 if (*ptr2) | |
257 linkscript.lines[linkscript.nlines].loadat = strtol(ptr2, NULL, 16); | |
258 else | |
259 linkscript.lines[linkscript.nlines].loadat = -1; | |
260 for (ptr2 = ptr; *ptr2 && *ptr2 != ','; ptr2++) | |
261 /* do nothing */ ; | |
262 if (*ptr2) | |
263 { | |
264 *ptr2++ = '\0'; | |
265 if (!strcmp(ptr2, "!bss")) | |
266 { | |
267 linkscript.lines[linkscript.nlines].noflags = SECTION_BSS; | |
268 } | |
269 else if (!strcmp(ptr2, "bss")) | |
270 { | |
271 linkscript.lines[linkscript.nlines].yesflags = SECTION_BSS; | |
272 } | |
273 else | |
274 { | |
275 fprintf(stderr, "%s: bad script\n", scriptfile); | |
276 exit(1); | |
277 } | |
278 } | |
279 if (ptr[0] == '*' && ptr[1] == '\0') | |
280 linkscript.lines[linkscript.nlines].sectname = NULL; | |
281 else | |
282 linkscript.lines[linkscript.nlines].sectname = lw_strdup(ptr); | |
283 linkscript.nlines++; | |
284 } | |
285 else | |
286 { | |
287 fprintf(stderr, "%s: bad script\n", scriptfile); | |
288 exit(1); | |
289 } | |
290 lw_free(line); | |
291 } | |
292 | |
293 if (scriptfile || nscriptls) | |
294 lw_free(oscript); | |
295 } |