Mercurial > hg-old > index.cgi
annotate lwlink/link.c @ 171:d610b8aef91b
Added LWAR skeleton
author | lost |
---|---|
date | Sun, 01 Mar 2009 19:37:03 +0000 |
parents | 106c2fe3c9d9 |
children | 0395e6fd67e9 |
rev | line source |
---|---|
119 | 1 /* |
2 link.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 Resolve section and symbol addresses; handle incomplete references | |
22 */ | |
23 | |
24 #ifdef HAVE_CONFIG_H | |
25 #include "config.h" | |
26 #endif | |
27 | |
120 | 28 #include <stdio.h> |
119 | 29 #include <stdlib.h> |
30 | |
120 | 31 #include "expr.h" |
119 | 32 #include "lwlink.h" |
33 #include "util.h" | |
34 | |
121 | 35 struct section_list *sectlist = NULL; |
36 int nsects = 0; | |
119 | 37 |
171 | 38 void check_section_name(char *name, int *base, fileinfo_t *fn) |
39 { | |
40 int sn; | |
41 for (sn = 0; sn < fn -> nsections; sn++) | |
42 { | |
43 if (!strcmp(name, fn -> sections[sn].name)) | |
44 { | |
45 // we have a match | |
46 sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1)); | |
47 sectlist[nsects].ptr = &(fn -> sections[sn]); | |
48 | |
49 fn -> sections[sn].processed = 1; | |
50 fn -> sections[sn].loadaddress = *base; | |
51 *base += fn -> sections[sn].codesize; | |
52 nsects++; | |
53 } | |
54 } | |
55 for (sn = 0; sn < fn -> nsubs; fn++) | |
56 { | |
57 check_section_name(name, base, fn -> subs[sn]); | |
58 } | |
59 } | |
60 | |
61 void add_matching_sections(char *name, int yesflags, int noflags, int *base); | |
62 void check_section_flags(int yesflags, int noflags, int *base, fileinfo_t *fn) | |
63 { | |
64 int sn; | |
65 for (sn = 0; sn < fn -> nsections; sn++) | |
66 { | |
67 // ignore if the noflags tell us to | |
68 if (noflags && (fn -> sections[sn].flags & noflags)) | |
69 continue; | |
70 // ignore unless the yesflags tell us not to | |
71 if (yesflags && (fn -> sections[sn].flags & yesflags == 0)) | |
72 continue; | |
73 // ignore it if already processed | |
74 if (fn -> sections[sn].processed) | |
75 continue; | |
76 | |
77 // we have a match - now collect *all* sections of the same name! | |
78 add_matching_sections(fn -> sections[sn].name, 0, 0, base); | |
79 | |
80 // and then continue looking for sections | |
81 } | |
82 for (sn = 0; sn < fn -> nsubs; fn++) | |
83 { | |
84 check_section_flags(yesflags, noflags, base, fn -> subs[sn]); | |
85 } | |
86 } | |
87 | |
88 | |
89 | |
90 void add_matching_sections(char *name, int yesflags, int noflags, int *base) | |
91 { | |
92 int fn; | |
93 if (name) | |
94 { | |
95 // named section | |
96 // look for all instances of a section by the specified name | |
97 // and resolve base addresses and add to the list | |
98 for (fn = 0; fn < ninputfiles; fn++) | |
99 { | |
100 check_section_name(name, base, inputfiles[fn]); | |
101 } | |
102 } | |
103 else | |
104 { | |
105 // wildcard section | |
106 // named section | |
107 // look for all instances of a section by the specified name | |
108 // and resolve base addresses and add to the list | |
109 for (fn = 0; fn < ninputfiles; fn++) | |
110 { | |
111 check_section_flags(yesflags, noflags, base, inputfiles[fn]); | |
112 } | |
113 } | |
114 } | |
115 | |
119 | 116 // work out section load order and resolve base addresses for each section |
117 // make a list of sections to load in order | |
118 void resolve_sections(void) | |
119 { | |
120 int laddr = 0; | |
121 int ln, sn, fn; | |
122 | |
123 for (ln = 0; ln < linkscript.nlines; ln++) | |
124 { | |
171 | 125 if (linkscript.lines[ln].loadat >= 0) |
126 laddr = linkscript.lines[ln].loadat; | |
127 add_matching_sections(linkscript.lines[ln].sectname, linkscript.lines[ln].yesflags, linkscript.lines[ln].noflags, &laddr); | |
128 | |
119 | 129 if (linkscript.lines[ln].sectname) |
130 { | |
131 } | |
132 else | |
133 { | |
134 // wildcard section | |
135 // look for all sections not yet processed that match flags | |
136 | |
137 int f = 0; | |
138 int fn0, sn0; | |
139 char *sname; | |
140 | |
141 // named section | |
142 // look for all instances of a section by the specified name | |
143 // and resolve base addresses and add to the list | |
144 for (fn0 = 0; fn0 < ninputfiles; fn0++) | |
145 { | |
146 for (sn0 = 0; sn0 < inputfiles[fn0] -> nsections; sn0++) | |
147 { | |
148 // ignore if the "no flags" bit says to | |
149 if (linkscript.lines[ln].noflags && (inputfiles[fn0] -> sections[sn0].flags & linkscript.lines[ln].noflags)) | |
150 continue; | |
151 // ignore unless the yes flags tell us not to | |
152 if (linkscript.lines[ln].yesflags && (inputfiles[fn0] -> sections[sn0].flags & linkscript.lines[ln].yesflags == 0)) | |
153 continue; | |
154 if (inputfiles[fn0] -> sections[sn0].processed == 0) | |
155 { | |
156 sname = inputfiles[fn0] -> sections[sn0].name; | |
157 for (fn = 0; fn < ninputfiles; fn++) | |
158 { | |
159 for (sn = 0; sn < inputfiles[fn] -> nsections; sn++) | |
160 { | |
161 if (!strcmp(sname, inputfiles[fn] -> sections[sn].name)) | |
162 { | |
163 // we have a match | |
164 sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1)); | |
165 sectlist[nsects].ptr = &(inputfiles[fn] -> sections[sn]); | |
166 | |
167 inputfiles[fn] -> sections[sn].processed = 1; | |
168 if (!f && linkscript.lines[ln].loadat >= 0) | |
169 { | |
170 f = 1; | |
171 sectlist[nsects].forceaddr = 1; | |
172 laddr = linkscript.lines[ln].loadat; | |
173 } | |
174 else | |
175 { | |
176 sectlist[nsects].forceaddr = 0; | |
177 } | |
178 inputfiles[fn] -> sections[sn].loadaddress = laddr; | |
131
5276565799bd
Fixed load addresses of chained sections and subsections to actually increment
lost
parents:
130
diff
changeset
|
179 laddr += inputfiles[fn] -> sections[sn].codesize; |
119 | 180 nsects++; |
181 } | |
182 } | |
183 } | |
184 } | |
185 } | |
186 } | |
187 } | |
188 } | |
189 | |
190 // theoretically, all the base addresses are set now | |
191 } | |
120 | 192 |
171 | 193 lw_expr_stack_t *find_external_sym_recurse(char *sym, fileinfo_t *fn) |
194 { | |
195 int sn; | |
196 lw_expr_stack_t *r; | |
197 lw_expr_term_t *term; | |
198 symtab_t *se; | |
199 int val; | |
200 | |
201 for (sn = 0; sn < fn -> nsections; sn++) | |
202 { | |
203 for (se = fn -> sections[sn].exportedsyms; se; se = se -> next) | |
204 { | |
205 if (!strcmp(sym, se -> sym)) | |
206 { | |
207 val = se -> offset + fn -> sections[sn].loadaddress; | |
208 r = lw_expr_stack_create(); | |
209 term = lw_expr_term_create_int(val & 0xffff); | |
210 lw_expr_stack_push(r, term); | |
211 lw_expr_term_free(term); | |
212 return r; | |
213 } | |
214 } | |
215 } | |
216 | |
217 for (sn = 0; sn < fn -> nsubs; sn++) | |
218 { | |
219 r = find_external_sym_recurse(sym, fn -> subs[sn]); | |
220 if (r) | |
221 return r; | |
222 } | |
223 return NULL; | |
224 } | |
225 | |
120 | 226 // resolve all incomplete references now |
227 // anything that is unresolvable at this stage will throw an error | |
228 // because we know the load address of every section now | |
229 lw_expr_stack_t *resolve_sym(char *sym, int symtype, void *state) | |
230 { | |
231 section_t *sect = state; | |
232 lw_expr_term_t *term; | |
233 int val = 0, i, fn; | |
234 lw_expr_stack_t *s; | |
235 symtab_t *se; | |
171 | 236 fileinfo_t *fp; |
237 | |
120 | 238 if (symtype == 1) |
239 { | |
240 // local symbol | |
241 if (!sym) | |
242 { | |
243 val = sect -> loadaddress; | |
244 goto out; | |
245 } | |
246 | |
247 // start with this section | |
248 for (se = sect -> localsyms; se; se = se -> next) | |
249 { | |
250 if (!strcmp(se -> sym, sym)) | |
251 { | |
252 val = se -> offset + sect -> loadaddress; | |
253 goto out; | |
254 } | |
255 } | |
256 // not in this section - check all sections in this file | |
257 for (i = 0; i < sect -> file -> nsections; i++) | |
258 { | |
259 for (se = sect -> file -> sections[i].localsyms; se; se = se -> next) | |
260 { | |
261 if (!strcmp(se -> sym, sym)) | |
262 { | |
263 val = se -> offset + sect -> file -> sections[i].loadaddress; | |
264 goto out; | |
265 } | |
266 } | |
267 } | |
268 // not found | |
269 fprintf(stderr, "Local symbol %s not found in %s:%s\n", sym, sect -> file -> filename, sect -> name); | |
270 exit(1); | |
271 } | |
272 else | |
273 { | |
274 // external symbol | |
275 // read all files in order until found (or not found) | |
171 | 276 for (fp = sect -> file; fp; fp = fp -> parent) |
277 { | |
278 s = find_external_sym_recurse(sym, fp); | |
279 if (s) | |
280 return s; | |
281 } | |
282 | |
120 | 283 for (fn = 0; fn < ninputfiles; fn++) |
284 { | |
171 | 285 s = find_external_sym_recurse(sym, inputfiles[fn]); |
286 if (s) | |
287 return s; | |
120 | 288 } |
130 | 289 if (sect) |
290 { | |
291 fprintf(stderr, "External symbol %s not found in %s:%s\n", sym, sect -> file -> filename, sect -> name); | |
292 } | |
293 else | |
294 { | |
295 fprintf(stderr, "External symbol %s not found\n", sym); | |
296 } | |
120 | 297 exit(1); |
298 } | |
299 fprintf(stderr, "Shouldn't ever get here!!!\n"); | |
300 exit(88); | |
301 out: | |
302 s = lw_expr_stack_create(); | |
303 term = lw_expr_term_create_int(val & 0xffff); | |
304 lw_expr_stack_push(s, term); | |
305 lw_expr_term_free(term); | |
306 return s; | |
307 } | |
308 | |
309 void resolve_references(void) | |
310 { | |
311 int sn; | |
312 reloc_t *rl; | |
313 int rval; | |
121 | 314 |
315 // resolve entry point if required | |
316 // this must resolve to an *exported* symbol and will resolve to the | |
317 // first instance of that symbol | |
318 if (linkscript.execsym) | |
319 { | |
320 lw_expr_stack_t *s; | |
321 | |
322 s = resolve_sym(linkscript.execsym, 0, NULL); | |
323 linkscript.execaddr = lw_expr_get_value(s); | |
324 lw_expr_stack_free(s); | |
325 } | |
120 | 326 |
124 | 327 for (sn = 0; sn < nsects; sn++) |
120 | 328 { |
329 for (rl = sectlist[sn].ptr -> incompletes; rl; rl = rl -> next) | |
330 { | |
331 // do a "simplify" on the expression | |
332 rval = lw_expr_reval(rl -> expr, resolve_sym, sectlist[sn].ptr); | |
333 | |
334 // is it constant? error out if not | |
335 if (rval != 0 || !lw_expr_is_constant(rl -> expr)) | |
336 { | |
337 fprintf(stderr, "Incomplete reference at %s:%s:%02X\n", sectlist[sn].ptr -> file -> filename, sectlist[sn].ptr -> name, rl -> offset); | |
338 exit(1); | |
339 } | |
340 | |
341 // put the value into the relocation address | |
342 rval = lw_expr_get_value(rl -> expr); | |
343 sectlist[sn].ptr -> code[rl -> offset] = (rval >> 8) & 0xff; | |
344 sectlist[sn].ptr -> code[rl -> offset + 1] = rval & 0xff; | |
345 } | |
346 } | |
347 } |