Mercurial > hg > index.cgi
comparison lwlink/link.c @ 315:fcd103148aa6
Add ability to load sections downward instead of upward
Add "section ... high ..." statement to link scripts to allow a section to
be placed based on its end address instead of its start address. All
sections listed after such a statement are treated as growing downward until
the next section statement specifying a load address.
author | William Astle <lost@l-w.ca> |
---|---|
date | Wed, 27 Nov 2013 16:01:26 -0700 |
parents | 346966cffeef |
children | 6821f4855702 |
comparison
equal
deleted
inserted
replaced
310:86eb8814a05c | 315:fcd103148aa6 |
---|---|
42 | 42 |
43 symlist_t *symlist = NULL; | 43 symlist_t *symlist = NULL; |
44 | 44 |
45 sectopt_t *section_opts = NULL; | 45 sectopt_t *section_opts = NULL; |
46 | 46 |
47 void check_section_name(char *name, int *base, fileinfo_t *fn) | 47 void check_section_name(char *name, int *base, fileinfo_t *fn, int down) |
48 { | 48 { |
49 int sn; | 49 int sn; |
50 // fprintf(stderr, "Considering sections in %s (%d) for %s\n", fn -> filename, fn -> forced, name); | 50 // fprintf(stderr, "Considering sections in %s (%d) for %s\n", fn -> filename, fn -> forced, name); |
51 if (fn -> forced == 0) | 51 if (fn -> forced == 0) |
52 return; | 52 return; |
62 // fprintf(stderr, " Found\n"); | 62 // fprintf(stderr, " Found\n"); |
63 sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1)); | 63 sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1)); |
64 sectlist[nsects].ptr = &(fn -> sections[sn]); | 64 sectlist[nsects].ptr = &(fn -> sections[sn]); |
65 | 65 |
66 fn -> sections[sn].processed = 1; | 66 fn -> sections[sn].processed = 1; |
67 fn -> sections[sn].loadaddress = *base; | 67 if (down) |
68 *base += fn -> sections[sn].codesize; | 68 { |
69 *base -= fn -> sections[sn].codesize; | |
70 fn -> sections[sn].loadaddress = *base; | |
71 } | |
72 else | |
73 { | |
74 fn -> sections[sn].loadaddress = *base; | |
75 *base += fn -> sections[sn].codesize; | |
76 } | |
69 nsects++; | 77 nsects++; |
70 // fprintf(stderr, "Adding section %s (%s)\n",fn -> sections[sn].name, fn -> filename); | 78 // fprintf(stderr, "Adding section %s (%s)\n",fn -> sections[sn].name, fn -> filename); |
71 } | 79 } |
72 } | 80 } |
73 for (sn = 0; sn < fn -> nsubs; sn++) | 81 for (sn = 0; sn < fn -> nsubs; sn++) |
74 { | 82 { |
75 check_section_name(name, base, fn -> subs[sn]); | 83 check_section_name(name, base, fn -> subs[sn], down); |
76 } | 84 } |
77 } | 85 } |
78 | 86 |
79 void add_matching_sections(char *name, int yesflags, int noflags, int *base); | 87 void add_matching_sections(char *name, int yesflags, int noflags, int *base, int down); |
80 void check_section_flags(int yesflags, int noflags, int *base, fileinfo_t *fn) | 88 void check_section_flags(int yesflags, int noflags, int *base, fileinfo_t *fn, int down) |
81 { | 89 { |
82 int sn; | 90 int sn; |
83 sectopt_t *so; | 91 sectopt_t *so; |
84 | 92 |
85 // fprintf(stderr, "Considering sections in %s (%d) for %x/%x\n", fn -> filename, fn -> forced, yesflags, noflags); | 93 // fprintf(stderr, "Considering sections in %s (%d) for %x/%x\n", fn -> filename, fn -> forced, yesflags, noflags); |
102 if (fn -> sections[sn].processed) | 110 if (fn -> sections[sn].processed) |
103 continue; | 111 continue; |
104 | 112 |
105 // we have a match - now collect *all* sections of the same name! | 113 // we have a match - now collect *all* sections of the same name! |
106 // fprintf(stderr, " Found\n"); | 114 // fprintf(stderr, " Found\n"); |
107 add_matching_sections((char *)(fn -> sections[sn].name), 0, 0, base); | 115 add_matching_sections((char *)(fn -> sections[sn].name), 0, 0, base, down); |
108 | 116 |
109 /* handle "after padding" */ | 117 /* handle "after padding" */ |
110 for (so = section_opts; so; so = so -> next) | 118 for (so = section_opts; so; so = so -> next) |
111 if (!strcmp(so -> name, (char *)(fn -> sections[sn].name))) | 119 if (!strcmp(so -> name, (char *)(fn -> sections[sn].name))) |
112 break; | 120 break; |
114 { | 122 { |
115 if (so -> aftersize) | 123 if (so -> aftersize) |
116 { | 124 { |
117 sectlist[nsects - 1].ptr -> afterbytes = so -> afterbytes; | 125 sectlist[nsects - 1].ptr -> afterbytes = so -> afterbytes; |
118 sectlist[nsects - 1].ptr -> aftersize = so -> aftersize; | 126 sectlist[nsects - 1].ptr -> aftersize = so -> aftersize; |
119 *base += so -> aftersize; | 127 if (down) |
128 { | |
129 sectlist[nsects - 1].ptr -> loadaddress -= so -> aftersize; | |
130 *base -= so -> aftersize; | |
131 } | |
132 else | |
133 { | |
134 *base += so -> aftersize; | |
135 } | |
120 } | 136 } |
121 } | 137 } |
122 | 138 |
123 // and then continue looking for sections | 139 // and then continue looking for sections |
124 } | 140 } |
125 for (sn = 0; sn < fn -> nsubs; sn++) | 141 for (sn = 0; sn < fn -> nsubs; sn++) |
126 { | 142 { |
127 check_section_flags(yesflags, noflags, base, fn -> subs[sn]); | 143 check_section_flags(yesflags, noflags, base, fn -> subs[sn], down); |
128 } | 144 } |
129 } | 145 } |
130 | 146 |
131 | 147 |
132 | 148 |
133 void add_matching_sections(char *name, int yesflags, int noflags, int *base) | 149 void add_matching_sections(char *name, int yesflags, int noflags, int *base, int down) |
134 { | 150 { |
135 int fn; | 151 int fn; |
136 if (name) | 152 if (name) |
137 { | 153 { |
138 // named section | 154 // named section |
139 // look for all instances of a section by the specified name | 155 // look for all instances of a section by the specified name |
140 // and resolve base addresses and add to the list | 156 // and resolve base addresses and add to the list |
141 for (fn = 0; fn < ninputfiles; fn++) | 157 for (fn = 0; fn < ninputfiles; fn++) |
142 { | 158 { |
143 check_section_name(name, base, inputfiles[fn]); | 159 check_section_name(name, base, inputfiles[fn], down); |
144 } | 160 } |
145 } | 161 } |
146 else | 162 else |
147 { | 163 { |
148 // wildcard section | 164 // wildcard section |
149 // named section | 165 // named section |
150 // look for all instances of a section by the specified name | 166 // look for all instances of a section by the specified name |
151 // and resolve base addresses and add to the list | 167 // and resolve base addresses and add to the list |
152 for (fn = 0; fn < ninputfiles; fn++) | 168 for (fn = 0; fn < ninputfiles; fn++) |
153 { | 169 { |
154 check_section_flags(yesflags, noflags, base, inputfiles[fn]); | 170 check_section_flags(yesflags, noflags, base, inputfiles[fn], down); |
155 } | 171 } |
156 } | 172 } |
157 } | 173 } |
158 | 174 |
159 // work out section load order and resolve base addresses for each section | 175 // work out section load order and resolve base addresses for each section |
160 // make a list of sections to load in order | 176 // make a list of sections to load in order |
161 void resolve_sections(void) | 177 void resolve_sections(void) |
162 { | 178 { |
163 int laddr = 0; | 179 int laddr = 0; |
180 int growdown = 0; | |
164 int ln, sn, fn; | 181 int ln, sn, fn; |
165 sectopt_t *so; | 182 sectopt_t *so; |
166 | 183 |
167 for (ln = 0; ln < linkscript.nlines; ln++) | 184 for (ln = 0; ln < linkscript.nlines; ln++) |
168 { | 185 { |
169 if (linkscript.lines[ln].loadat >= 0) | 186 if (linkscript.lines[ln].loadat >= 0) |
187 { | |
170 laddr = linkscript.lines[ln].loadat; | 188 laddr = linkscript.lines[ln].loadat; |
189 growdown = linkscript.lines[ln].growsdown; | |
190 } | |
171 //fprintf(stderr, "Adding section %s\n", linkscript.lines[ln].sectname); | 191 //fprintf(stderr, "Adding section %s\n", linkscript.lines[ln].sectname); |
172 add_matching_sections(linkscript.lines[ln].sectname, linkscript.lines[ln].yesflags, linkscript.lines[ln].noflags, &laddr); | 192 add_matching_sections(linkscript.lines[ln].sectname, linkscript.lines[ln].yesflags, linkscript.lines[ln].noflags, &laddr, growdown); |
173 | 193 |
174 if (linkscript.lines[ln].sectname) | 194 if (linkscript.lines[ln].sectname) |
175 { | 195 { |
176 char *sname = linkscript.lines[ln].sectname; | 196 char *sname = linkscript.lines[ln].sectname; |
177 /* handle "after padding" */ | 197 /* handle "after padding" */ |
182 { | 202 { |
183 if (so -> aftersize) | 203 if (so -> aftersize) |
184 { | 204 { |
185 sectlist[nsects - 1].ptr -> afterbytes = so -> afterbytes; | 205 sectlist[nsects - 1].ptr -> afterbytes = so -> afterbytes; |
186 sectlist[nsects - 1].ptr -> aftersize = so -> aftersize; | 206 sectlist[nsects - 1].ptr -> aftersize = so -> aftersize; |
187 laddr += so -> aftersize; | 207 if (growdown) |
208 { | |
209 sectlist[nsects-1].ptr -> loadaddress -= so -> aftersize; | |
210 laddr -= so -> aftersize; | |
211 } | |
212 else | |
213 { | |
214 laddr += so -> aftersize; | |
215 } | |
188 } | 216 } |
189 } | 217 } |
190 } | 218 } |
191 else | 219 else |
192 { | 220 { |
231 if (!f && linkscript.lines[ln].loadat >= 0) | 259 if (!f && linkscript.lines[ln].loadat >= 0) |
232 { | 260 { |
233 f = 1; | 261 f = 1; |
234 sectlist[nsects].forceaddr = 1; | 262 sectlist[nsects].forceaddr = 1; |
235 laddr = linkscript.lines[ln].loadat; | 263 laddr = linkscript.lines[ln].loadat; |
264 growdown = linkscript.lines[ln].growsdown; | |
236 } | 265 } |
237 else | 266 else |
238 { | 267 { |
239 sectlist[nsects].forceaddr = 0; | 268 sectlist[nsects].forceaddr = 0; |
240 } | 269 } |
241 inputfiles[fn] -> sections[sn].loadaddress = laddr; | 270 if (growdown) |
242 laddr += inputfiles[fn] -> sections[sn].codesize; | 271 { |
272 laddr -= inputfiles[fn] -> sections[sn].codesize; | |
273 inputfiles[fn] -> sections[sn].loadaddress = laddr; | |
274 } | |
275 else | |
276 { | |
277 inputfiles[fn] -> sections[sn].loadaddress = laddr; | |
278 laddr += inputfiles[fn] -> sections[sn].codesize; | |
279 } | |
243 nsects++; | 280 nsects++; |
244 } | 281 } |
245 } | 282 } |
246 } | 283 } |
247 } | 284 } |
259 int sn; | 296 int sn; |
260 char *lastsect = NULL; | 297 char *lastsect = NULL; |
261 char sym[256]; | 298 char sym[256]; |
262 int len; | 299 int len; |
263 symlist_t *se; | 300 symlist_t *se; |
301 int lowaddr; | |
302 | |
264 for (sn = 0; sn < nsects; sn++) | 303 for (sn = 0; sn < nsects; sn++) |
265 { | 304 { |
266 if (!lastsect || strcmp(lastsect, (char *)(sectlist[sn].ptr -> name))) | 305 if (!lastsect || strcmp(lastsect, (char *)(sectlist[sn].ptr -> name))) |
267 { | 306 { |
268 if (lastsect && linkscript.lensympat) | 307 if (lastsect && linkscript.lensympat) |
273 snprintf(sym, 255, linkscript.lensympat, lastsect); | 312 snprintf(sym, 255, linkscript.lensympat, lastsect); |
274 se -> sym = lw_strdup(sym); | 313 se -> sym = lw_strdup(sym); |
275 se -> next = symlist; | 314 se -> next = symlist; |
276 symlist = se; | 315 symlist = se; |
277 } | 316 } |
278 lastsect = (char *)(sectlist[sn].ptr -> name); | |
279 len = 0; | |
280 /* handle base symbol */ | |
281 if (lastsect && linkscript.basesympat) | 317 if (lastsect && linkscript.basesympat) |
282 { | 318 { |
283 se = lw_alloc(sizeof(symlist_t)); | 319 se = lw_alloc(sizeof(symlist_t)); |
284 se -> val = sectlist[sn].ptr -> loadaddress; | 320 se -> val = lowaddr; |
285 snprintf(sym, 255, linkscript.basesympat, lastsect); | 321 snprintf(sym, 255, linkscript.basesympat, lastsect); |
286 se -> sym = lw_strdup(sym); | 322 se -> sym = lw_strdup(sym); |
287 se -> next = symlist; | 323 se -> next = symlist; |
288 symlist = se; | 324 symlist = se; |
289 } | 325 } |
326 lastsect = (char *)(sectlist[sn].ptr -> name); | |
327 len = 0; | |
328 lowaddr = sectlist[sn].ptr -> loadaddress; | |
290 } | 329 } |
291 len += sectlist[sn].ptr -> codesize; | 330 len += sectlist[sn].ptr -> codesize; |
331 if (sectlist[sn].ptr -> loadaddress < lowaddr) | |
332 lowaddr = sectlist[sn].ptr -> loadaddress; | |
292 } | 333 } |
293 if (lastsect && linkscript.lensympat) | 334 if (lastsect && linkscript.lensympat) |
294 { | 335 { |
295 /* handle length symbol */ | 336 /* handle length symbol */ |
296 se = lw_alloc(sizeof(symlist_t)); | 337 se = lw_alloc(sizeof(symlist_t)); |
298 snprintf(sym, 255, linkscript.lensympat, lastsect); | 339 snprintf(sym, 255, linkscript.lensympat, lastsect); |
299 se -> sym = lw_strdup(sym); | 340 se -> sym = lw_strdup(sym); |
300 se -> next = symlist; | 341 se -> next = symlist; |
301 symlist = se; | 342 symlist = se; |
302 } | 343 } |
303 | 344 if (lastsect && linkscript.basesympat) |
345 { | |
346 se = lw_alloc(sizeof(symlist_t)); | |
347 se -> val = lowaddr; | |
348 snprintf(sym, 255, linkscript.basesympat, lastsect); | |
349 se -> sym = lw_strdup(sym); | |
350 se -> next = symlist; | |
351 symlist = se; | |
352 } | |
304 } | 353 } |
305 | 354 |
306 lw_expr_stack_t *find_external_sym_recurse(char *sym, fileinfo_t *fn) | 355 lw_expr_stack_t *find_external_sym_recurse(char *sym, fileinfo_t *fn) |
307 { | 356 { |
308 int sn; | 357 int sn; |