# HG changeset patch # User lost # Date 1232516725 0 # Node ID 376cc55361c79eb709e9a670c97d9710fca94d8f # Parent 48945dac81781ad624e99068054fe2c8b53a4599 section order and address resolution done diff -r 48945dac8178 -r 376cc55361c7 src/Makefile.am --- a/src/Makefile.am Wed Jan 21 05:13:36 2009 +0000 +++ b/src/Makefile.am Wed Jan 21 05:45:25 2009 +0000 @@ -1,3 +1,3 @@ bin_PROGRAMS = lwlink -lwlink_SOURCES = main.c lwlink.c util.c readfiles.c expr.c script.c +lwlink_SOURCES = main.c lwlink.c util.c readfiles.c expr.c script.c link.c EXTRA_DIST = lwlink.h util.h expr.h diff -r 48945dac8178 -r 376cc55361c7 src/link.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/link.c Wed Jan 21 05:45:25 2009 +0000 @@ -0,0 +1,142 @@ +/* +link.c +Copyright © 2009 William Astle + +This file is part of LWLINK. + +LWLINK is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . + + +Resolve section and symbol addresses; handle incomplete references +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "lwlink.h" +#include "util.h" + +struct section_list +{ + section_t *ptr; // ptr to section structure + int forceaddr; // was this force to an address by the link script? +}; + +static struct section_list *sectlist = NULL; +static int nsects = 0; + +// work out section load order and resolve base addresses for each section +// make a list of sections to load in order +void resolve_sections(void) +{ + int laddr = 0; + int ln, sn, fn; + + for (ln = 0; ln < linkscript.nlines; ln++) + { + if (linkscript.lines[ln].sectname) + { + int f = 0; + // named section + // look for all instances of a section by the specified name + // and resolve base addresses and add to the list + for (fn = 0; fn < ninputfiles; fn++) + { + for (sn = 0; sn < inputfiles[fn] -> nsections; sn++) + { + if (!strcmp(linkscript.lines[ln].sectname, inputfiles[fn] -> sections[sn].name)) + { + // we have a match + sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1)); + sectlist[nsects].ptr = &(inputfiles[fn] -> sections[sn]); + + inputfiles[fn] -> sections[sn].processed = 1; + if (!f && linkscript.lines[ln].loadat >= 0) + { + f = 1; + sectlist[nsects].forceaddr = 1; + laddr = linkscript.lines[ln].loadat; + } + else + { + sectlist[nsects].forceaddr = 0; + } + inputfiles[fn] -> sections[sn].loadaddress = laddr; + nsects++; + } + } + } + } + else + { + // wildcard section + // look for all sections not yet processed that match flags + + int f = 0; + int fn0, sn0; + char *sname; + + // named section + // look for all instances of a section by the specified name + // and resolve base addresses and add to the list + for (fn0 = 0; fn0 < ninputfiles; fn0++) + { + for (sn0 = 0; sn0 < inputfiles[fn0] -> nsections; sn0++) + { + // ignore if the "no flags" bit says to + if (linkscript.lines[ln].noflags && (inputfiles[fn0] -> sections[sn0].flags & linkscript.lines[ln].noflags)) + continue; + // ignore unless the yes flags tell us not to + if (linkscript.lines[ln].yesflags && (inputfiles[fn0] -> sections[sn0].flags & linkscript.lines[ln].yesflags == 0)) + continue; + if (inputfiles[fn0] -> sections[sn0].processed == 0) + { + sname = inputfiles[fn0] -> sections[sn0].name; + for (fn = 0; fn < ninputfiles; fn++) + { + for (sn = 0; sn < inputfiles[fn] -> nsections; sn++) + { + if (!strcmp(sname, inputfiles[fn] -> sections[sn].name)) + { + // we have a match + sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1)); + sectlist[nsects].ptr = &(inputfiles[fn] -> sections[sn]); + + inputfiles[fn] -> sections[sn].processed = 1; + if (!f && linkscript.lines[ln].loadat >= 0) + { + f = 1; + sectlist[nsects].forceaddr = 1; + laddr = linkscript.lines[ln].loadat; + } + else + { + sectlist[nsects].forceaddr = 0; + } + inputfiles[fn] -> sections[sn].loadaddress = laddr; + nsects++; + } + } + } + } + } + } + } + } + + // theoretically, all the base addresses are set now +} diff -r 48945dac8178 -r 376cc55361c7 src/lwlink.h --- a/src/lwlink.h Wed Jan 21 05:13:36 2009 +0000 +++ b/src/lwlink.h Wed Jan 21 05:45:25 2009 +0000 @@ -46,6 +46,8 @@ reloc_t *next; // ptr to next relocation }; +typedef struct fileinfo_s fileinfo_t; + #define SECTION_BSS 1 typedef struct { @@ -54,14 +56,17 @@ int codesize; // size of the code unsigned char *code; // pointer to the code int loadaddress; // the actual load address of the section - + int processed; // was the section processed yet? + symtab_t *localsyms; // local symbol table symtab_t *exportedsyms; // exported symbols table reloc_t *incompletes; // table of incomplete references + + fileinfo_t *file; // the file we are in } section_t; -typedef struct +struct fileinfo_s { char *filename; unsigned char *filedata; @@ -69,7 +74,7 @@ section_t *sections; int nsections; -} fileinfo_t; +}; diff -r 48945dac8178 -r 376cc55361c7 src/main.c --- a/src/main.c Wed Jan 21 05:13:36 2009 +0000 +++ b/src/main.c Wed Jan 21 05:45:25 2009 +0000 @@ -121,6 +121,7 @@ extern void read_files(void); extern void setup_script(void); +extern void resolve_sections(void); // main function; parse command line, set up assembler state, and run the // assembler on the first file @@ -133,10 +134,14 @@ exit(1); } + // handle the linker script setup_script(); // read the input files read_files(); + // resolve section bases and section order + resolve_sections(); + exit(0); } diff -r 48945dac8178 -r 376cc55361c7 src/readfiles.c --- a/src/readfiles.c Wed Jan 21 05:13:36 2009 +0000 +++ b/src/readfiles.c Wed Jan 21 05:45:25 2009 +0000 @@ -145,7 +145,9 @@ s -> localsyms = NULL; s -> exportedsyms = NULL; s -> incompletes = NULL; - + s -> processed = 0; + s -> file = fn; + // read flags while (CURBYTE()) { diff -r 48945dac8178 -r 376cc55361c7 src/script.c --- a/src/script.c Wed Jan 21 05:13:36 2009 +0000 +++ b/src/script.c Wed Jan 21 05:45:25 2009 +0000 @@ -220,7 +220,10 @@ exit(1); } } - linkscript.lines[linkscript.nlines].sectname = lw_strdup(ptr); + if (ptr[0] == '*' && ptr[1] == '\0') + linkscript.lines[linkscript.nlines].sectname = NULL; + else + linkscript.lines[linkscript.nlines].sectname = lw_strdup(ptr); linkscript.nlines++; } else