comparison old-trunk/lwlink/script.c @ 339:eb230fa7d28e

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