diff src/link.c @ 302:eff969272fb9

resolve incomplete references done
author lost
date Wed, 21 Jan 2009 06:14:08 +0000
parents 376cc55361c7
children 13272197d278
line wrap: on
line diff
--- a/src/link.c	Wed Jan 21 05:45:25 2009 +0000
+++ b/src/link.c	Wed Jan 21 06:14:08 2009 +0000
@@ -25,8 +25,10 @@
 #include "config.h"
 #endif
 
+#include <stdio.h>
 #include <stdlib.h>
 
+#include "expr.h"
 #include "lwlink.h"
 #include "util.h"
 
@@ -140,3 +142,107 @@
 	
 	// theoretically, all the base addresses are set now
 }
+
+// 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
+lw_expr_stack_t *resolve_sym(char *sym, int symtype, void *state)
+{
+	section_t *sect = state;
+	lw_expr_term_t *term;
+	int val = 0, i, fn;
+	lw_expr_stack_t *s;
+	symtab_t *se;
+	
+	if (symtype == 1)
+	{
+		// local symbol
+		if (!sym)
+		{
+			val = sect -> loadaddress;
+			goto out;
+		}
+		
+		// start with this section
+		for (se = sect -> localsyms; se; se = se -> next)
+		{
+			if (!strcmp(se -> sym, sym))
+			{
+				val = se -> offset + sect -> loadaddress;
+				goto out;
+			}
+		}
+		// not in this section - check all sections in this file
+		for (i = 0; i < sect -> file -> nsections; i++)
+		{
+			for (se = sect -> file -> sections[i].localsyms; se; se = se -> next)
+			{
+				if (!strcmp(se -> sym, sym))
+				{
+					val = se -> offset + sect -> file -> sections[i].loadaddress;
+					goto out;
+				}
+			}
+		}
+		// not found
+		fprintf(stderr, "Local symbol %s not found in %s:%s\n", sym, sect -> file -> filename, sect -> name);
+		exit(1);
+	}
+	else
+	{
+		// external symbol
+		// read all files in order until found (or not found)
+		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;
+					}
+				}
+			}
+		}
+		fprintf(stderr, "External symbol %s not found in %s:%s\n", sym, sect -> file -> filename, sect -> name);
+		exit(1);
+	}
+	fprintf(stderr, "Shouldn't ever get here!!!\n");
+	exit(88);
+out:
+	s = lw_expr_stack_create();
+	term = lw_expr_term_create_int(val & 0xffff);
+	lw_expr_stack_push(s, term);
+	lw_expr_term_free(term);
+	return s;
+}
+
+void resolve_references(void)
+{
+	int sn;
+	reloc_t *rl;
+	int rval;
+	
+	for (sn = 0; nsects; sn++)
+	{
+		for (rl = sectlist[sn].ptr -> incompletes; rl; rl = rl -> next)
+		{
+			// do a "simplify" on the expression
+			rval = lw_expr_reval(rl -> expr, resolve_sym, sectlist[sn].ptr);
+
+			// is it constant? error out if not
+			if (rval != 0 || !lw_expr_is_constant(rl -> expr))
+			{
+				fprintf(stderr, "Incomplete reference at %s:%s:%02X\n", sectlist[sn].ptr -> file -> filename, sectlist[sn].ptr -> name, rl -> offset);
+				exit(1);
+			}
+			
+			// put the value into the relocation address
+			rval = lw_expr_get_value(rl -> expr);
+			sectlist[sn].ptr -> code[rl -> offset] = (rval >> 8) & 0xff;
+			sectlist[sn].ptr -> code[rl -> offset + 1] = rval & 0xff;
+		}
+	}
+}