diff lwlink/link.c @ 171:d610b8aef91b

Added LWAR skeleton
author lost
date Sun, 01 Mar 2009 19:37:03 +0000
parents 106c2fe3c9d9
children 0395e6fd67e9
line wrap: on
line diff
--- a/lwlink/link.c	Sun Mar 01 00:53:21 2009 +0000
+++ b/lwlink/link.c	Sun Mar 01 19:37:03 2009 +0000
@@ -35,6 +35,84 @@
 struct section_list *sectlist = NULL;
 int nsects = 0;
 
+void check_section_name(char *name, int *base, fileinfo_t *fn)
+{
+	int sn;
+	for (sn = 0; sn < fn -> nsections; sn++)
+	{
+		if (!strcmp(name, fn -> sections[sn].name))
+		{
+			// we have a match
+			sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1));
+			sectlist[nsects].ptr = &(fn -> sections[sn]);
+					
+			fn -> sections[sn].processed = 1;
+			fn -> sections[sn].loadaddress = *base;
+			*base += fn -> sections[sn].codesize;
+			nsects++;
+		}
+	}
+	for (sn = 0; sn < fn -> nsubs; fn++)
+	{
+		check_section_name(name, base, fn -> subs[sn]);
+	}
+}
+
+void add_matching_sections(char *name, int yesflags, int noflags, int *base);
+void check_section_flags(int yesflags, int noflags, int *base, fileinfo_t *fn)
+{
+	int sn;
+	for (sn = 0; sn < fn -> nsections; sn++)
+	{
+		// ignore if the noflags tell us to
+		if (noflags && (fn -> sections[sn].flags & noflags))
+			continue;
+		// ignore unless the yesflags tell us not to
+		if (yesflags && (fn -> sections[sn].flags & yesflags == 0))
+			continue;
+		// ignore it if already processed
+		if (fn -> sections[sn].processed)
+			continue;
+
+		// we have a match - now collect *all* sections of the same name!
+		add_matching_sections(fn -> sections[sn].name, 0, 0, base);
+		
+		// and then continue looking for sections
+	}
+	for (sn = 0; sn < fn -> nsubs; fn++)
+	{
+		check_section_flags(yesflags, noflags, base, fn -> subs[sn]);
+	}
+}
+
+
+
+void add_matching_sections(char *name, int yesflags, int noflags, int *base)
+{
+	int fn;
+	if (name)
+	{
+		// 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++)
+		{
+			check_section_name(name, base, inputfiles[fn]);
+		}
+	}
+	else
+	{
+		// wildcard section
+		// 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++)
+		{
+			check_section_flags(yesflags, noflags, base, inputfiles[fn]);
+		}
+	}
+}
+
 // 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)
@@ -44,41 +122,12 @@
 	
 	for (ln = 0; ln < linkscript.nlines; ln++)
 	{
-//	printf("Linker script line %d: '%s', %04X, %d, %d\n", ln, linkscript.lines[ln].sectname, linkscript.lines[ln].loadat, linkscript.lines[ln].yesflags, linkscript.lines[ln].noflags);
+		if (linkscript.lines[ln].loadat >= 0)
+			laddr = linkscript.lines[ln].loadat;
+		add_matching_sections(linkscript.lines[ln].sectname, linkscript.lines[ln].yesflags, linkscript.lines[ln].noflags, &laddr);
+		
 		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++)
-				{
-//				printf("  Considering %s:%s\n", inputfiles[fn]->filename, inputfiles[fn]->sections[sn].name);
-					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;
-						laddr += inputfiles[fn] -> sections[sn].codesize;
-						nsects++;
-					}
-				}
-			}
 		}
 		else
 		{
@@ -141,6 +190,39 @@
 	// theoretically, all the base addresses are set now
 }
 
+lw_expr_stack_t *find_external_sym_recurse(char *sym, fileinfo_t *fn)
+{
+	int sn;
+	lw_expr_stack_t *r;
+	lw_expr_term_t *term;
+	symtab_t *se;
+	int val;
+	
+	for (sn = 0; sn < fn -> nsections; sn++)
+	{
+		for (se = fn -> sections[sn].exportedsyms; se; se = se -> next)
+		{
+			if (!strcmp(sym, se -> sym))
+			{
+				val = se -> offset + fn -> sections[sn].loadaddress;
+				r = lw_expr_stack_create();
+				term = lw_expr_term_create_int(val & 0xffff);
+				lw_expr_stack_push(r, term);
+				lw_expr_term_free(term);
+				return r;
+			}
+		}
+	}
+		
+	for (sn = 0; sn < fn -> nsubs; sn++)
+	{
+		r = find_external_sym_recurse(sym, fn -> subs[sn]);
+		if (r)
+			return r;
+	}
+	return NULL;
+}
+
 // resolve all incomplete references now
 // anything that is unresolvable at this stage will throw an error
 // because we know the load address of every section now
@@ -151,7 +233,8 @@
 	int val = 0, i, fn;
 	lw_expr_stack_t *s;
 	symtab_t *se;
-	
+	fileinfo_t *fp;
+
 	if (symtype == 1)
 	{
 		// local symbol
@@ -190,19 +273,18 @@
 	{
 		// external symbol
 		// read all files in order until found (or not found)
+		for (fp = sect -> file; fp; fp = fp -> parent)
+		{
+			s = find_external_sym_recurse(sym, fp);
+			if (s)
+				return s;
+		}
+
 		for (fn = 0; fn < ninputfiles; fn++)
 		{
-			for (i = 0; i < inputfiles[fn] -> nsections; i++)
-			{
-				for (se = inputfiles[fn] -> sections[i].exportedsyms; se; se = se -> next)
-				{
-					if (!strcmp(sym, se -> sym))
-					{
-						val = se -> offset + inputfiles[fn] -> sections[i].loadaddress;
-						goto out;
-					}
-				}
-			}
+			s = find_external_sym_recurse(sym, inputfiles[fn]);
+			if (s)
+				return s;
 		}
 		if (sect)
 		{