changeset 120:36ce328df3c3

resolve incomplete references done
author lost
date Wed, 21 Jan 2009 06:14:08 +0000
parents 8bc00221ae89
children 7bc853cb2ca9
files lwlink/trunk/src/link.c lwlink/trunk/src/lwlink.h lwlink/trunk/src/readfiles.c
diffstat 3 files changed, 108 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/lwlink/trunk/src/link.c	Wed Jan 21 05:45:25 2009 +0000
+++ b/lwlink/trunk/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;
+		}
+	}
+}
--- a/lwlink/trunk/src/lwlink.h	Wed Jan 21 05:45:25 2009 +0000
+++ b/lwlink/trunk/src/lwlink.h	Wed Jan 21 06:14:08 2009 +0000
@@ -34,7 +34,7 @@
 {
 	unsigned char *sym;		// symbol name
 	int offset;				// local offset
-	int realval;			// resolved value
+//	int realval;			// resolved value
 	symtab_t *next;			// next symbol
 };
 
--- a/lwlink/trunk/src/readfiles.c	Wed Jan 21 05:45:25 2009 +0000
+++ b/lwlink/trunk/src/readfiles.c	Wed Jan 21 06:14:08 2009 +0000
@@ -184,7 +184,6 @@
 			s -> localsyms = se;
 			se -> sym = fp;
 			se -> offset = val;
-			se -> realval = val;
 		}
 
 		// now parse the exported symbol table
@@ -205,7 +204,6 @@
 			s -> localsyms = se;
 			se -> sym = fp;
 			se -> offset = val;
-			se -> realval = val;
 		}
 		
 		// now parse the incomplete references and make a list of
@@ -260,7 +258,7 @@
 				case 0x05:
 					// section base reference (NULL internal reference is
 					// the section base address
-					term = lw_expr_term_create_sym(NULL, 0);
+					term = lw_expr_term_create_sym(NULL, 1);
 					break;
 					
 				default: