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 }