# HG changeset patch # User William Astle # Date 1385593286 25200 # Node ID fcd103148aa61c247f4dda43457bc393dd8140d6 # Parent 86eb8814a05ca19458562127a5875a312189ba37 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. diff -r 86eb8814a05c -r fcd103148aa6 lwlink/link.c --- a/lwlink/link.c Tue Nov 12 21:03:48 2013 -0700 +++ b/lwlink/link.c Wed Nov 27 16:01:26 2013 -0700 @@ -44,7 +44,7 @@ sectopt_t *section_opts = NULL; -void check_section_name(char *name, int *base, fileinfo_t *fn) +void check_section_name(char *name, int *base, fileinfo_t *fn, int down) { int sn; // fprintf(stderr, "Considering sections in %s (%d) for %s\n", fn -> filename, fn -> forced, name); @@ -64,20 +64,28 @@ sectlist[nsects].ptr = &(fn -> sections[sn]); fn -> sections[sn].processed = 1; - fn -> sections[sn].loadaddress = *base; - *base += fn -> sections[sn].codesize; + if (down) + { + *base -= fn -> sections[sn].codesize; + fn -> sections[sn].loadaddress = *base; + } + else + { + fn -> sections[sn].loadaddress = *base; + *base += fn -> sections[sn].codesize; + } nsects++; // fprintf(stderr, "Adding section %s (%s)\n",fn -> sections[sn].name, fn -> filename); } } for (sn = 0; sn < fn -> nsubs; sn++) { - check_section_name(name, base, fn -> subs[sn]); + check_section_name(name, base, fn -> subs[sn], down); } } -void add_matching_sections(char *name, int yesflags, int noflags, int *base); -void check_section_flags(int yesflags, int noflags, int *base, fileinfo_t *fn) +void add_matching_sections(char *name, int yesflags, int noflags, int *base, int down); +void check_section_flags(int yesflags, int noflags, int *base, fileinfo_t *fn, int down) { int sn; sectopt_t *so; @@ -104,7 +112,7 @@ // we have a match - now collect *all* sections of the same name! // fprintf(stderr, " Found\n"); - add_matching_sections((char *)(fn -> sections[sn].name), 0, 0, base); + add_matching_sections((char *)(fn -> sections[sn].name), 0, 0, base, down); /* handle "after padding" */ for (so = section_opts; so; so = so -> next) @@ -116,7 +124,15 @@ { sectlist[nsects - 1].ptr -> afterbytes = so -> afterbytes; sectlist[nsects - 1].ptr -> aftersize = so -> aftersize; - *base += so -> aftersize; + if (down) + { + sectlist[nsects - 1].ptr -> loadaddress -= so -> aftersize; + *base -= so -> aftersize; + } + else + { + *base += so -> aftersize; + } } } @@ -124,13 +140,13 @@ } for (sn = 0; sn < fn -> nsubs; sn++) { - check_section_flags(yesflags, noflags, base, fn -> subs[sn]); + check_section_flags(yesflags, noflags, base, fn -> subs[sn], down); } } -void add_matching_sections(char *name, int yesflags, int noflags, int *base) +void add_matching_sections(char *name, int yesflags, int noflags, int *base, int down) { int fn; if (name) @@ -140,7 +156,7 @@ // and resolve base addresses and add to the list for (fn = 0; fn < ninputfiles; fn++) { - check_section_name(name, base, inputfiles[fn]); + check_section_name(name, base, inputfiles[fn], down); } } else @@ -151,7 +167,7 @@ // and resolve base addresses and add to the list for (fn = 0; fn < ninputfiles; fn++) { - check_section_flags(yesflags, noflags, base, inputfiles[fn]); + check_section_flags(yesflags, noflags, base, inputfiles[fn], down); } } } @@ -161,15 +177,19 @@ void resolve_sections(void) { int laddr = 0; + int growdown = 0; int ln, sn, fn; sectopt_t *so; for (ln = 0; ln < linkscript.nlines; ln++) { if (linkscript.lines[ln].loadat >= 0) + { laddr = linkscript.lines[ln].loadat; + growdown = linkscript.lines[ln].growsdown; + } //fprintf(stderr, "Adding section %s\n", linkscript.lines[ln].sectname); - add_matching_sections(linkscript.lines[ln].sectname, linkscript.lines[ln].yesflags, linkscript.lines[ln].noflags, &laddr); + add_matching_sections(linkscript.lines[ln].sectname, linkscript.lines[ln].yesflags, linkscript.lines[ln].noflags, &laddr, growdown); if (linkscript.lines[ln].sectname) { @@ -184,7 +204,15 @@ { sectlist[nsects - 1].ptr -> afterbytes = so -> afterbytes; sectlist[nsects - 1].ptr -> aftersize = so -> aftersize; - laddr += so -> aftersize; + if (growdown) + { + sectlist[nsects-1].ptr -> loadaddress -= so -> aftersize; + laddr -= so -> aftersize; + } + else + { + laddr += so -> aftersize; + } } } } @@ -233,13 +261,22 @@ f = 1; sectlist[nsects].forceaddr = 1; laddr = linkscript.lines[ln].loadat; + growdown = linkscript.lines[ln].growsdown; } else { sectlist[nsects].forceaddr = 0; } - inputfiles[fn] -> sections[sn].loadaddress = laddr; - laddr += inputfiles[fn] -> sections[sn].codesize; + if (growdown) + { + laddr -= inputfiles[fn] -> sections[sn].codesize; + inputfiles[fn] -> sections[sn].loadaddress = laddr; + } + else + { + inputfiles[fn] -> sections[sn].loadaddress = laddr; + laddr += inputfiles[fn] -> sections[sn].codesize; + } nsects++; } } @@ -261,6 +298,8 @@ char sym[256]; int len; symlist_t *se; + int lowaddr; + for (sn = 0; sn < nsects; sn++) { if (!lastsect || strcmp(lastsect, (char *)(sectlist[sn].ptr -> name))) @@ -275,20 +314,22 @@ se -> next = symlist; symlist = se; } - lastsect = (char *)(sectlist[sn].ptr -> name); - len = 0; - /* handle base symbol */ if (lastsect && linkscript.basesympat) { se = lw_alloc(sizeof(symlist_t)); - se -> val = sectlist[sn].ptr -> loadaddress; + se -> val = lowaddr; snprintf(sym, 255, linkscript.basesympat, lastsect); se -> sym = lw_strdup(sym); se -> next = symlist; symlist = se; } + lastsect = (char *)(sectlist[sn].ptr -> name); + len = 0; + lowaddr = sectlist[sn].ptr -> loadaddress; } len += sectlist[sn].ptr -> codesize; + if (sectlist[sn].ptr -> loadaddress < lowaddr) + lowaddr = sectlist[sn].ptr -> loadaddress; } if (lastsect && linkscript.lensympat) { @@ -300,7 +341,15 @@ se -> next = symlist; symlist = se; } - + if (lastsect && linkscript.basesympat) + { + se = lw_alloc(sizeof(symlist_t)); + se -> val = lowaddr; + snprintf(sym, 255, linkscript.basesympat, lastsect); + se -> sym = lw_strdup(sym); + se -> next = symlist; + symlist = se; + } } lw_expr_stack_t *find_external_sym_recurse(char *sym, fileinfo_t *fn) diff -r 86eb8814a05c -r fcd103148aa6 lwlink/lwlink.h --- a/lwlink/lwlink.h Tue Nov 12 21:03:48 2013 -0700 +++ b/lwlink/lwlink.h Wed Nov 27 16:01:26 2013 -0700 @@ -156,6 +156,7 @@ int loadat; // address to load at (or -1) int noflags; // flags to NOT have int yesflags; // flags to HAVE + int growsdown; // sections are placed descending in memory }; typedef struct diff -r 86eb8814a05c -r fcd103148aa6 lwlink/script.c --- a/lwlink/script.c Tue Nov 12 21:03:48 2013 -0700 +++ b/lwlink/script.c Wed Nov 27 16:01:26 2013 -0700 @@ -380,6 +380,7 @@ } else if (!strcmp(line, "section")) { + int growsdown = 0; // section // parse out the section name and flags for (ptr2 = ptr; *ptr2 && !isspace(*ptr2); ptr2++) @@ -404,12 +405,24 @@ ptr2++; } + else if (!strncmp(ptr2, "high", 4)) + { + ptr2 += 4; + while (*ptr2 && isspace(*ptr2)) + ptr2++; + growsdown = 1; + } else { fprintf(stderr, "%s: bad script\n", scriptfile); exit(1); } } + else + { + if (linkscript.nlines > 0) + growsdown = linkscript.lines[linkscript.nlines - 1].growsdown; + } // now ptr2 points to the load address if there is one // or NUL if not @@ -417,6 +430,7 @@ linkscript.lines[linkscript.nlines].noflags = 0; linkscript.lines[linkscript.nlines].yesflags = 0; + linkscript.lines[linkscript.nlines].growsdown = growsdown; if (*ptr2) linkscript.lines[linkscript.nlines].loadat = strtol(ptr2, NULL, 16); else