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;