changeset 301:376cc55361c7

section order and address resolution done
author lost
date Wed, 21 Jan 2009 05:45:25 +0000
parents 48945dac8178
children eff969272fb9
files src/Makefile.am src/link.c src/lwlink.h src/main.c src/readfiles.c src/script.c
diffstat 6 files changed, 163 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- 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
--- /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 <http://www.gnu.org/licenses/>.
+
+
+Resolve section and symbol addresses; handle incomplete references
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+
+#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
+}
--- 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;
+};
 
 
 
--- 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);
 }
--- 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())
 		{
--- 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