annotate src/script.c @ 301:376cc55361c7

section order and address resolution done
author lost
date Wed, 21 Jan 2009 05:45:25 +0000
parents 48945dac8178
children 13272197d278
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
299
460d96987670 parse linking scripts
lost
parents:
diff changeset
1 /*
460d96987670 parse linking scripts
lost
parents:
diff changeset
2 script.c
300
48945dac8178 Fixed copyright year
lost
parents: 299
diff changeset
3 Copyright © 2009 William Astle
299
460d96987670 parse linking scripts
lost
parents:
diff changeset
4
460d96987670 parse linking scripts
lost
parents:
diff changeset
5 This file is part of LWLINK.
460d96987670 parse linking scripts
lost
parents:
diff changeset
6
460d96987670 parse linking scripts
lost
parents:
diff changeset
7 LWLINK is free software: you can redistribute it and/or modify it under the
460d96987670 parse linking scripts
lost
parents:
diff changeset
8 terms of the GNU General Public License as published by the Free Software
460d96987670 parse linking scripts
lost
parents:
diff changeset
9 Foundation, either version 3 of the License, or (at your option) any later
460d96987670 parse linking scripts
lost
parents:
diff changeset
10 version.
460d96987670 parse linking scripts
lost
parents:
diff changeset
11
460d96987670 parse linking scripts
lost
parents:
diff changeset
12 This program is distributed in the hope that it will be useful, but WITHOUT
460d96987670 parse linking scripts
lost
parents:
diff changeset
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
460d96987670 parse linking scripts
lost
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
460d96987670 parse linking scripts
lost
parents:
diff changeset
15 more details.
460d96987670 parse linking scripts
lost
parents:
diff changeset
16
460d96987670 parse linking scripts
lost
parents:
diff changeset
17 You should have received a copy of the GNU General Public License along with
460d96987670 parse linking scripts
lost
parents:
diff changeset
18 this program. If not, see <http://www.gnu.org/licenses/>.
460d96987670 parse linking scripts
lost
parents:
diff changeset
19
460d96987670 parse linking scripts
lost
parents:
diff changeset
20
460d96987670 parse linking scripts
lost
parents:
diff changeset
21 Read and parse linker scripts
460d96987670 parse linking scripts
lost
parents:
diff changeset
22 */
460d96987670 parse linking scripts
lost
parents:
diff changeset
23
460d96987670 parse linking scripts
lost
parents:
diff changeset
24 #ifdef HAVE_CONFIG_H
460d96987670 parse linking scripts
lost
parents:
diff changeset
25 #include "config.h"
460d96987670 parse linking scripts
lost
parents:
diff changeset
26 #endif
460d96987670 parse linking scripts
lost
parents:
diff changeset
27
460d96987670 parse linking scripts
lost
parents:
diff changeset
28 #include <errno.h>
460d96987670 parse linking scripts
lost
parents:
diff changeset
29 #include <stdio.h>
460d96987670 parse linking scripts
lost
parents:
diff changeset
30 #include <stdlib.h>
460d96987670 parse linking scripts
lost
parents:
diff changeset
31 #include <string.h>
460d96987670 parse linking scripts
lost
parents:
diff changeset
32
460d96987670 parse linking scripts
lost
parents:
diff changeset
33 #include "lwlink.h"
460d96987670 parse linking scripts
lost
parents:
diff changeset
34 #include "util.h"
460d96987670 parse linking scripts
lost
parents:
diff changeset
35
460d96987670 parse linking scripts
lost
parents:
diff changeset
36 // the built-in DECB target linker script
460d96987670 parse linking scripts
lost
parents:
diff changeset
37 static char *decb_script =
460d96987670 parse linking scripts
lost
parents:
diff changeset
38 "section init load at 2000\n"
460d96987670 parse linking scripts
lost
parents:
diff changeset
39 "section code\n"
460d96987670 parse linking scripts
lost
parents:
diff changeset
40 "section *,!bss\n"
460d96987670 parse linking scripts
lost
parents:
diff changeset
41 "section *,bss\n"
460d96987670 parse linking scripts
lost
parents:
diff changeset
42 ;
460d96987670 parse linking scripts
lost
parents:
diff changeset
43
460d96987670 parse linking scripts
lost
parents:
diff changeset
44 // the built-in RAW target linker script
460d96987670 parse linking scripts
lost
parents:
diff changeset
45 static char *raw_script =
460d96987670 parse linking scripts
lost
parents:
diff changeset
46 "section init load at 0000\n"
460d96987670 parse linking scripts
lost
parents:
diff changeset
47 "section code\n"
460d96987670 parse linking scripts
lost
parents:
diff changeset
48 "section *,!bss\n"
460d96987670 parse linking scripts
lost
parents:
diff changeset
49 "section *,bss\n"
460d96987670 parse linking scripts
lost
parents:
diff changeset
50 ;
460d96987670 parse linking scripts
lost
parents:
diff changeset
51
460d96987670 parse linking scripts
lost
parents:
diff changeset
52 // the "simple" script
460d96987670 parse linking scripts
lost
parents:
diff changeset
53 static char *simple_script =
460d96987670 parse linking scripts
lost
parents:
diff changeset
54 "section *,!bss\n"
460d96987670 parse linking scripts
lost
parents:
diff changeset
55 "section *,bss\n"
460d96987670 parse linking scripts
lost
parents:
diff changeset
56 ;
460d96987670 parse linking scripts
lost
parents:
diff changeset
57
460d96987670 parse linking scripts
lost
parents:
diff changeset
58 linkscript_t linkscript = { 0, NULL, -1 };
460d96987670 parse linking scripts
lost
parents:
diff changeset
59
460d96987670 parse linking scripts
lost
parents:
diff changeset
60 void setup_script()
460d96987670 parse linking scripts
lost
parents:
diff changeset
61 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
62 char *script;
460d96987670 parse linking scripts
lost
parents:
diff changeset
63 long size;
460d96987670 parse linking scripts
lost
parents:
diff changeset
64
460d96987670 parse linking scripts
lost
parents:
diff changeset
65 // read the file if needed
460d96987670 parse linking scripts
lost
parents:
diff changeset
66 if (scriptfile)
460d96987670 parse linking scripts
lost
parents:
diff changeset
67 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
68 FILE *f;
460d96987670 parse linking scripts
lost
parents:
diff changeset
69 long bread;
460d96987670 parse linking scripts
lost
parents:
diff changeset
70
460d96987670 parse linking scripts
lost
parents:
diff changeset
71 f = fopen(scriptfile, "rb");
460d96987670 parse linking scripts
lost
parents:
diff changeset
72 if (!f)
460d96987670 parse linking scripts
lost
parents:
diff changeset
73 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
74 fprintf(stderr, "Can't open file %s:", scriptfile);
460d96987670 parse linking scripts
lost
parents:
diff changeset
75 perror("");
460d96987670 parse linking scripts
lost
parents:
diff changeset
76 exit(1);
460d96987670 parse linking scripts
lost
parents:
diff changeset
77 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
78 fseek(f, 0, SEEK_END);
460d96987670 parse linking scripts
lost
parents:
diff changeset
79 size = ftell(f);
460d96987670 parse linking scripts
lost
parents:
diff changeset
80 rewind(f);
460d96987670 parse linking scripts
lost
parents:
diff changeset
81
460d96987670 parse linking scripts
lost
parents:
diff changeset
82 script = lw_malloc(size + 2);
460d96987670 parse linking scripts
lost
parents:
diff changeset
83
460d96987670 parse linking scripts
lost
parents:
diff changeset
84 bread = fread(script, 1, size, f);
460d96987670 parse linking scripts
lost
parents:
diff changeset
85 if (bread < size)
460d96987670 parse linking scripts
lost
parents:
diff changeset
86 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
87 fprintf(stderr, "Short read on file %s (%ld/%ld):", scriptfile, bread, size);
460d96987670 parse linking scripts
lost
parents:
diff changeset
88 perror("");
460d96987670 parse linking scripts
lost
parents:
diff changeset
89 exit(1);
460d96987670 parse linking scripts
lost
parents:
diff changeset
90 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
91 fclose(f);
460d96987670 parse linking scripts
lost
parents:
diff changeset
92
460d96987670 parse linking scripts
lost
parents:
diff changeset
93 script[size] = '\n';
460d96987670 parse linking scripts
lost
parents:
diff changeset
94 script[size + 1] = '\0';
460d96987670 parse linking scripts
lost
parents:
diff changeset
95 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
96 else
460d96987670 parse linking scripts
lost
parents:
diff changeset
97 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
98 // fetch defaults based on output mode
460d96987670 parse linking scripts
lost
parents:
diff changeset
99 switch (outformat)
460d96987670 parse linking scripts
lost
parents:
diff changeset
100 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
101 case OUTPUT_RAW:
460d96987670 parse linking scripts
lost
parents:
diff changeset
102 script = raw_script;
460d96987670 parse linking scripts
lost
parents:
diff changeset
103 break;
460d96987670 parse linking scripts
lost
parents:
diff changeset
104
460d96987670 parse linking scripts
lost
parents:
diff changeset
105 case OUTPUT_DECB:
460d96987670 parse linking scripts
lost
parents:
diff changeset
106 script = decb_script;
460d96987670 parse linking scripts
lost
parents:
diff changeset
107 break;
460d96987670 parse linking scripts
lost
parents:
diff changeset
108
460d96987670 parse linking scripts
lost
parents:
diff changeset
109 default:
460d96987670 parse linking scripts
lost
parents:
diff changeset
110 script = simple_script;
460d96987670 parse linking scripts
lost
parents:
diff changeset
111 break;
460d96987670 parse linking scripts
lost
parents:
diff changeset
112 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
113
460d96987670 parse linking scripts
lost
parents:
diff changeset
114 size = strlen(script);
460d96987670 parse linking scripts
lost
parents:
diff changeset
115 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
116
460d96987670 parse linking scripts
lost
parents:
diff changeset
117 // now parse the script file
460d96987670 parse linking scripts
lost
parents:
diff changeset
118 while (*script)
460d96987670 parse linking scripts
lost
parents:
diff changeset
119 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
120 char *ptr, *ptr2, *line;
460d96987670 parse linking scripts
lost
parents:
diff changeset
121
460d96987670 parse linking scripts
lost
parents:
diff changeset
122 for (ptr = script; *ptr && *ptr != '\n' && *ptr != '\r'; ptr++)
460d96987670 parse linking scripts
lost
parents:
diff changeset
123 /* do nothing */ ;
460d96987670 parse linking scripts
lost
parents:
diff changeset
124
460d96987670 parse linking scripts
lost
parents:
diff changeset
125 line = lw_malloc(ptr - script + 1);
460d96987670 parse linking scripts
lost
parents:
diff changeset
126 memcpy(line, script, ptr - script);
460d96987670 parse linking scripts
lost
parents:
diff changeset
127 line[ptr - script] = '\0';
460d96987670 parse linking scripts
lost
parents:
diff changeset
128
460d96987670 parse linking scripts
lost
parents:
diff changeset
129 // skip line terms
460d96987670 parse linking scripts
lost
parents:
diff changeset
130 for (script = ptr + 1; *script == '\n' || *script == '\r'; script++)
460d96987670 parse linking scripts
lost
parents:
diff changeset
131 /* do nothing */ ;
460d96987670 parse linking scripts
lost
parents:
diff changeset
132
460d96987670 parse linking scripts
lost
parents:
diff changeset
133 // ignore leading whitespace
460d96987670 parse linking scripts
lost
parents:
diff changeset
134 for (ptr = line; *ptr && isspace(*ptr); ptr++)
460d96987670 parse linking scripts
lost
parents:
diff changeset
135 /* do nothing */ ;
460d96987670 parse linking scripts
lost
parents:
diff changeset
136
460d96987670 parse linking scripts
lost
parents:
diff changeset
137 // ignore blank lines
460d96987670 parse linking scripts
lost
parents:
diff changeset
138 if (!*ptr)
460d96987670 parse linking scripts
lost
parents:
diff changeset
139 continue;
460d96987670 parse linking scripts
lost
parents:
diff changeset
140
460d96987670 parse linking scripts
lost
parents:
diff changeset
141 for (ptr = line; *ptr && !isspace(*ptr); ptr++)
460d96987670 parse linking scripts
lost
parents:
diff changeset
142 /* do nothing */ ;
460d96987670 parse linking scripts
lost
parents:
diff changeset
143
460d96987670 parse linking scripts
lost
parents:
diff changeset
144 // now ptr points to the char past the first word
460d96987670 parse linking scripts
lost
parents:
diff changeset
145 // NUL it out
460d96987670 parse linking scripts
lost
parents:
diff changeset
146 if (*ptr)
460d96987670 parse linking scripts
lost
parents:
diff changeset
147 *ptr++ = '\0';
460d96987670 parse linking scripts
lost
parents:
diff changeset
148
460d96987670 parse linking scripts
lost
parents:
diff changeset
149 // skip spaces after the first word
460d96987670 parse linking scripts
lost
parents:
diff changeset
150 for ( ; *ptr && isspace(*ptr); ptr++)
460d96987670 parse linking scripts
lost
parents:
diff changeset
151 /* do nothing */ ;
460d96987670 parse linking scripts
lost
parents:
diff changeset
152
460d96987670 parse linking scripts
lost
parents:
diff changeset
153 if (!strcmp(line, "pad"))
460d96987670 parse linking scripts
lost
parents:
diff changeset
154 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
155 // padding
460d96987670 parse linking scripts
lost
parents:
diff changeset
156 // parse the hex number and stow it
460d96987670 parse linking scripts
lost
parents:
diff changeset
157 linkscript.padsize = strtol(ptr, NULL, 16);
460d96987670 parse linking scripts
lost
parents:
diff changeset
158 if (linkscript.padsize < 0)
460d96987670 parse linking scripts
lost
parents:
diff changeset
159 linkscript.padsize = 0;
460d96987670 parse linking scripts
lost
parents:
diff changeset
160 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
161 else if (!strcmp(line, "section"))
460d96987670 parse linking scripts
lost
parents:
diff changeset
162 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
163 // section
460d96987670 parse linking scripts
lost
parents:
diff changeset
164 // parse out the section name and flags
460d96987670 parse linking scripts
lost
parents:
diff changeset
165 for (ptr2 = ptr; *ptr2 && !isspace(*ptr2); ptr2++)
460d96987670 parse linking scripts
lost
parents:
diff changeset
166 /* do nothing */ ;
460d96987670 parse linking scripts
lost
parents:
diff changeset
167
460d96987670 parse linking scripts
lost
parents:
diff changeset
168 if (*ptr2)
460d96987670 parse linking scripts
lost
parents:
diff changeset
169 *ptr2++ = '\0';
460d96987670 parse linking scripts
lost
parents:
diff changeset
170
460d96987670 parse linking scripts
lost
parents:
diff changeset
171 while (*ptr2 && isspace(*ptr2))
460d96987670 parse linking scripts
lost
parents:
diff changeset
172 ptr2++;
460d96987670 parse linking scripts
lost
parents:
diff changeset
173
460d96987670 parse linking scripts
lost
parents:
diff changeset
174 // ptr now points to the section name and flags and ptr2
460d96987670 parse linking scripts
lost
parents:
diff changeset
175 // to the first non-space character following
460d96987670 parse linking scripts
lost
parents:
diff changeset
176
460d96987670 parse linking scripts
lost
parents:
diff changeset
177 // then look for "load <addr>" clause
460d96987670 parse linking scripts
lost
parents:
diff changeset
178 if (*ptr2)
460d96987670 parse linking scripts
lost
parents:
diff changeset
179 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
180 if (!strncmp(ptr2, "load", 4))
460d96987670 parse linking scripts
lost
parents:
diff changeset
181 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
182 ptr2 += 4;
460d96987670 parse linking scripts
lost
parents:
diff changeset
183 while (*ptr2 && isspace(*ptr2))
460d96987670 parse linking scripts
lost
parents:
diff changeset
184 ptr2++;
460d96987670 parse linking scripts
lost
parents:
diff changeset
185
460d96987670 parse linking scripts
lost
parents:
diff changeset
186 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
187 else
460d96987670 parse linking scripts
lost
parents:
diff changeset
188 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
189 fprintf(stderr, "%s: bad script\n", scriptfile);
460d96987670 parse linking scripts
lost
parents:
diff changeset
190 exit(1);
460d96987670 parse linking scripts
lost
parents:
diff changeset
191 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
192 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
193
460d96987670 parse linking scripts
lost
parents:
diff changeset
194 // now ptr2 points to the load address if there is one
460d96987670 parse linking scripts
lost
parents:
diff changeset
195 // or NUL if not
460d96987670 parse linking scripts
lost
parents:
diff changeset
196 linkscript.lines = lw_realloc(linkscript.lines, sizeof(struct scriptline_s) * (linkscript.nlines + 1));
460d96987670 parse linking scripts
lost
parents:
diff changeset
197
460d96987670 parse linking scripts
lost
parents:
diff changeset
198 linkscript.lines[linkscript.nlines].noflags = 0;
460d96987670 parse linking scripts
lost
parents:
diff changeset
199 linkscript.lines[linkscript.nlines].yesflags = 0;
460d96987670 parse linking scripts
lost
parents:
diff changeset
200 if (*ptr2)
460d96987670 parse linking scripts
lost
parents:
diff changeset
201 linkscript.lines[linkscript.nlines].loadat = strtol(ptr2, NULL, 16);
460d96987670 parse linking scripts
lost
parents:
diff changeset
202 else
460d96987670 parse linking scripts
lost
parents:
diff changeset
203 linkscript.lines[linkscript.nlines].loadat = -1;
460d96987670 parse linking scripts
lost
parents:
diff changeset
204 for (ptr2 = ptr; *ptr2 && *ptr2 != ','; ptr2++)
460d96987670 parse linking scripts
lost
parents:
diff changeset
205 /* do nothing */ ;
460d96987670 parse linking scripts
lost
parents:
diff changeset
206 if (*ptr2)
460d96987670 parse linking scripts
lost
parents:
diff changeset
207 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
208 *ptr2++ = '\0';
460d96987670 parse linking scripts
lost
parents:
diff changeset
209 if (!strcmp(ptr2, "!bss"))
460d96987670 parse linking scripts
lost
parents:
diff changeset
210 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
211 linkscript.lines[linkscript.nlines].noflags = SECTION_BSS;
460d96987670 parse linking scripts
lost
parents:
diff changeset
212 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
213 else if (!strcmp(ptr2, "bss"))
460d96987670 parse linking scripts
lost
parents:
diff changeset
214 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
215 linkscript.lines[linkscript.nlines].yesflags = SECTION_BSS;
460d96987670 parse linking scripts
lost
parents:
diff changeset
216 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
217 else
460d96987670 parse linking scripts
lost
parents:
diff changeset
218 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
219 fprintf(stderr, "%s: bad script\n", scriptfile);
460d96987670 parse linking scripts
lost
parents:
diff changeset
220 exit(1);
460d96987670 parse linking scripts
lost
parents:
diff changeset
221 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
222 }
301
376cc55361c7 section order and address resolution done
lost
parents: 300
diff changeset
223 if (ptr[0] == '*' && ptr[1] == '\0')
376cc55361c7 section order and address resolution done
lost
parents: 300
diff changeset
224 linkscript.lines[linkscript.nlines].sectname = NULL;
376cc55361c7 section order and address resolution done
lost
parents: 300
diff changeset
225 else
376cc55361c7 section order and address resolution done
lost
parents: 300
diff changeset
226 linkscript.lines[linkscript.nlines].sectname = lw_strdup(ptr);
299
460d96987670 parse linking scripts
lost
parents:
diff changeset
227 linkscript.nlines++;
460d96987670 parse linking scripts
lost
parents:
diff changeset
228 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
229 else
460d96987670 parse linking scripts
lost
parents:
diff changeset
230 {
460d96987670 parse linking scripts
lost
parents:
diff changeset
231 fprintf(stderr, "%s: bad script\n", scriptfile);
460d96987670 parse linking scripts
lost
parents:
diff changeset
232 exit(1);
460d96987670 parse linking scripts
lost
parents:
diff changeset
233 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
234 lw_free(line);
460d96987670 parse linking scripts
lost
parents:
diff changeset
235 }
460d96987670 parse linking scripts
lost
parents:
diff changeset
236
460d96987670 parse linking scripts
lost
parents:
diff changeset
237 if (scriptfile)
460d96987670 parse linking scripts
lost
parents:
diff changeset
238 lw_free(script);
460d96987670 parse linking scripts
lost
parents:
diff changeset
239 }