diff lwlink/link.c @ 234:d389adbcc4ab

Added section base and length symbols to lwlink Added the ability for a link script to define section base and section length symbols when linking. These symbols are searched for when an external reference is resolved before looking up any symbols in the various objects being linked. Also documented the new link script directives and added such directives to all default link scripts.
author William Astle <lost@l-w.ca>
date Fri, 10 Aug 2012 23:47:56 -0600
parents 4682460aed00
children e3741cf53e00
line wrap: on
line diff
--- a/lwlink/link.c	Thu Jul 19 13:17:30 2012 -0600
+++ b/lwlink/link.c	Fri Aug 10 23:47:56 2012 -0600
@@ -26,6 +26,7 @@
 #include <string.h>
 
 #include <lw_alloc.h>
+#include <lw_string.h>
 
 #include "expr.h"
 #include "lwlink.h"
@@ -37,6 +38,8 @@
 static int nforced = 0;
 static int resolveonly = 0;
 
+symlist_t *symlist = NULL;
+
 void check_section_name(char *name, int *base, fileinfo_t *fn)
 {
 	int sn;
@@ -215,6 +218,58 @@
 	// theoretically, all the base addresses are set now
 }
 
+/* run through all sections and generate any synthetic symbols */
+void generate_symbols(void)
+{
+	int sn;
+	char *lastsect = NULL;
+	char sym[256];
+	int len;
+	symlist_t *se;
+fprintf(stderr, "Generating symbols\n");	
+	for (sn = 0; sn < nsects; sn++)
+	{
+		fprintf(stderr, "Section %s (%s)\n", sectlist[sn].ptr -> name, lastsect);
+		if (!lastsect || strcmp(lastsect, (char *)(sectlist[sn].ptr -> name)))
+		{
+			if (lastsect && linkscript.lensympat)
+			{
+				/* handle length symbol */
+				se = lw_alloc(sizeof(symlist_t));
+				se -> val = len;
+				snprintf(sym, 255, linkscript.lensympat, lastsect);
+				se -> sym = lw_strdup(sym);
+				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;
+				snprintf(sym, 255, linkscript.basesympat, lastsect);
+				se -> sym = lw_strdup(sym);
+				se -> next = symlist;
+				symlist = se;
+			}
+		}
+		len += sectlist[sn].ptr -> codesize;
+	}
+	if (lastsect && linkscript.lensympat)
+	{
+		/* handle length symbol */
+		se = lw_alloc(sizeof(symlist_t));
+		se -> val = len;
+		snprintf(sym, 255, linkscript.lensympat, lastsect);
+		se -> sym = lw_strdup(sym);
+		se -> next = symlist;
+		symlist = se;
+	}
+
+}
+
 lw_expr_stack_t *find_external_sym_recurse(char *sym, fileinfo_t *fn)
 {
 	int sn;
@@ -350,7 +405,19 @@
 	}
 	else
 	{
+		symlist_t *se;
+		
 		// external symbol
+		// first look up synthesized symbols
+		for (se = symlist; se; se = se -> next)
+		{
+			if (!strcmp(se -> sym, sym))
+			{
+				val = se -> val;
+				goto out;
+			}
+		}
+		
 		// read all files in order until found (or not found)
 		if (sect)
 		{