# 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