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