Mercurial > hg-old > index.cgi
comparison lwlink/link.c @ 139:106c2fe3c9d9
repo reorg
author | lost |
---|---|
date | Wed, 28 Jan 2009 05:59:14 +0000 |
parents | lwlink-old/trunk/src/link.c@050864a47b38 |
children | d610b8aef91b |
comparison
equal
deleted
inserted
replaced
138:050864a47b38 | 139:106c2fe3c9d9 |
---|---|
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 | |
28 #include <stdio.h> | |
29 #include <stdlib.h> | |
30 | |
31 #include "expr.h" | |
32 #include "lwlink.h" | |
33 #include "util.h" | |
34 | |
35 struct section_list *sectlist = NULL; | |
36 int nsects = 0; | |
37 | |
38 // work out section load order and resolve base addresses for each section | |
39 // make a list of sections to load in order | |
40 void resolve_sections(void) | |
41 { | |
42 int laddr = 0; | |
43 int ln, sn, fn; | |
44 | |
45 for (ln = 0; ln < linkscript.nlines; ln++) | |
46 { | |
47 // printf("Linker script line %d: '%s', %04X, %d, %d\n", ln, linkscript.lines[ln].sectname, linkscript.lines[ln].loadat, linkscript.lines[ln].yesflags, linkscript.lines[ln].noflags); | |
48 if (linkscript.lines[ln].sectname) | |
49 { | |
50 int f = 0; | |
51 // named section | |
52 // look for all instances of a section by the specified name | |
53 // and resolve base addresses and add to the list | |
54 for (fn = 0; fn < ninputfiles; fn++) | |
55 { | |
56 for (sn = 0; sn < inputfiles[fn] -> nsections; sn++) | |
57 { | |
58 // printf(" Considering %s:%s\n", inputfiles[fn]->filename, inputfiles[fn]->sections[sn].name); | |
59 if (!strcmp(linkscript.lines[ln].sectname, inputfiles[fn] -> sections[sn].name)) | |
60 { | |
61 // we have a match | |
62 sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1)); | |
63 sectlist[nsects].ptr = &(inputfiles[fn] -> sections[sn]); | |
64 | |
65 inputfiles[fn] -> sections[sn].processed = 1; | |
66 if (!f && linkscript.lines[ln].loadat >= 0) | |
67 { | |
68 f = 1; | |
69 sectlist[nsects].forceaddr = 1; | |
70 laddr = linkscript.lines[ln].loadat; | |
71 } | |
72 else | |
73 { | |
74 sectlist[nsects].forceaddr = 0; | |
75 } | |
76 inputfiles[fn] -> sections[sn].loadaddress = laddr; | |
77 laddr += inputfiles[fn] -> sections[sn].codesize; | |
78 nsects++; | |
79 } | |
80 } | |
81 } | |
82 } | |
83 else | |
84 { | |
85 // wildcard section | |
86 // look for all sections not yet processed that match flags | |
87 | |
88 int f = 0; | |
89 int fn0, sn0; | |
90 char *sname; | |
91 | |
92 // named section | |
93 // look for all instances of a section by the specified name | |
94 // and resolve base addresses and add to the list | |
95 for (fn0 = 0; fn0 < ninputfiles; fn0++) | |
96 { | |
97 for (sn0 = 0; sn0 < inputfiles[fn0] -> nsections; sn0++) | |
98 { | |
99 // ignore if the "no flags" bit says to | |
100 if (linkscript.lines[ln].noflags && (inputfiles[fn0] -> sections[sn0].flags & linkscript.lines[ln].noflags)) | |
101 continue; | |
102 // ignore unless the yes flags tell us not to | |
103 if (linkscript.lines[ln].yesflags && (inputfiles[fn0] -> sections[sn0].flags & linkscript.lines[ln].yesflags == 0)) | |
104 continue; | |
105 if (inputfiles[fn0] -> sections[sn0].processed == 0) | |
106 { | |
107 sname = inputfiles[fn0] -> sections[sn0].name; | |
108 for (fn = 0; fn < ninputfiles; fn++) | |
109 { | |
110 for (sn = 0; sn < inputfiles[fn] -> nsections; sn++) | |
111 { | |
112 if (!strcmp(sname, inputfiles[fn] -> sections[sn].name)) | |
113 { | |
114 // we have a match | |
115 sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1)); | |
116 sectlist[nsects].ptr = &(inputfiles[fn] -> sections[sn]); | |
117 | |
118 inputfiles[fn] -> sections[sn].processed = 1; | |
119 if (!f && linkscript.lines[ln].loadat >= 0) | |
120 { | |
121 f = 1; | |
122 sectlist[nsects].forceaddr = 1; | |
123 laddr = linkscript.lines[ln].loadat; | |
124 } | |
125 else | |
126 { | |
127 sectlist[nsects].forceaddr = 0; | |
128 } | |
129 inputfiles[fn] -> sections[sn].loadaddress = laddr; | |
130 laddr += inputfiles[fn] -> sections[sn].codesize; | |
131 nsects++; | |
132 } | |
133 } | |
134 } | |
135 } | |
136 } | |
137 } | |
138 } | |
139 } | |
140 | |
141 // theoretically, all the base addresses are set now | |
142 } | |
143 | |
144 // resolve all incomplete references now | |
145 // anything that is unresolvable at this stage will throw an error | |
146 // because we know the load address of every section now | |
147 lw_expr_stack_t *resolve_sym(char *sym, int symtype, void *state) | |
148 { | |
149 section_t *sect = state; | |
150 lw_expr_term_t *term; | |
151 int val = 0, i, fn; | |
152 lw_expr_stack_t *s; | |
153 symtab_t *se; | |
154 | |
155 if (symtype == 1) | |
156 { | |
157 // local symbol | |
158 if (!sym) | |
159 { | |
160 val = sect -> loadaddress; | |
161 goto out; | |
162 } | |
163 | |
164 // start with this section | |
165 for (se = sect -> localsyms; se; se = se -> next) | |
166 { | |
167 if (!strcmp(se -> sym, sym)) | |
168 { | |
169 val = se -> offset + sect -> loadaddress; | |
170 goto out; | |
171 } | |
172 } | |
173 // not in this section - check all sections in this file | |
174 for (i = 0; i < sect -> file -> nsections; i++) | |
175 { | |
176 for (se = sect -> file -> sections[i].localsyms; se; se = se -> next) | |
177 { | |
178 if (!strcmp(se -> sym, sym)) | |
179 { | |
180 val = se -> offset + sect -> file -> sections[i].loadaddress; | |
181 goto out; | |
182 } | |
183 } | |
184 } | |
185 // not found | |
186 fprintf(stderr, "Local symbol %s not found in %s:%s\n", sym, sect -> file -> filename, sect -> name); | |
187 exit(1); | |
188 } | |
189 else | |
190 { | |
191 // external symbol | |
192 // read all files in order until found (or not found) | |
193 for (fn = 0; fn < ninputfiles; fn++) | |
194 { | |
195 for (i = 0; i < inputfiles[fn] -> nsections; i++) | |
196 { | |
197 for (se = inputfiles[fn] -> sections[i].exportedsyms; se; se = se -> next) | |
198 { | |
199 if (!strcmp(sym, se -> sym)) | |
200 { | |
201 val = se -> offset + inputfiles[fn] -> sections[i].loadaddress; | |
202 goto out; | |
203 } | |
204 } | |
205 } | |
206 } | |
207 if (sect) | |
208 { | |
209 fprintf(stderr, "External symbol %s not found in %s:%s\n", sym, sect -> file -> filename, sect -> name); | |
210 } | |
211 else | |
212 { | |
213 fprintf(stderr, "External symbol %s not found\n", sym); | |
214 } | |
215 exit(1); | |
216 } | |
217 fprintf(stderr, "Shouldn't ever get here!!!\n"); | |
218 exit(88); | |
219 out: | |
220 s = lw_expr_stack_create(); | |
221 term = lw_expr_term_create_int(val & 0xffff); | |
222 lw_expr_stack_push(s, term); | |
223 lw_expr_term_free(term); | |
224 return s; | |
225 } | |
226 | |
227 void resolve_references(void) | |
228 { | |
229 int sn; | |
230 reloc_t *rl; | |
231 int rval; | |
232 | |
233 // resolve entry point if required | |
234 // this must resolve to an *exported* symbol and will resolve to the | |
235 // first instance of that symbol | |
236 if (linkscript.execsym) | |
237 { | |
238 lw_expr_stack_t *s; | |
239 | |
240 s = resolve_sym(linkscript.execsym, 0, NULL); | |
241 linkscript.execaddr = lw_expr_get_value(s); | |
242 lw_expr_stack_free(s); | |
243 } | |
244 | |
245 for (sn = 0; sn < nsects; sn++) | |
246 { | |
247 for (rl = sectlist[sn].ptr -> incompletes; rl; rl = rl -> next) | |
248 { | |
249 // do a "simplify" on the expression | |
250 rval = lw_expr_reval(rl -> expr, resolve_sym, sectlist[sn].ptr); | |
251 | |
252 // is it constant? error out if not | |
253 if (rval != 0 || !lw_expr_is_constant(rl -> expr)) | |
254 { | |
255 fprintf(stderr, "Incomplete reference at %s:%s:%02X\n", sectlist[sn].ptr -> file -> filename, sectlist[sn].ptr -> name, rl -> offset); | |
256 exit(1); | |
257 } | |
258 | |
259 // put the value into the relocation address | |
260 rval = lw_expr_get_value(rl -> expr); | |
261 sectlist[sn].ptr -> code[rl -> offset] = (rval >> 8) & 0xff; | |
262 sectlist[sn].ptr -> code[rl -> offset + 1] = rval & 0xff; | |
263 } | |
264 } | |
265 } |