diff src/link.c @ 301:376cc55361c7

section order and address resolution done
author lost
date Wed, 21 Jan 2009 05:45:25 +0000
parents
children eff969272fb9
line wrap: on
line diff
--- /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
+}