changeset 91:718998b673ee

Added incomplete references to object output and added support for section base terms in expression handler
author lost
date Sat, 17 Jan 2009 05:56:40 +0000
parents 6097cb1486f8
children ea2cfebef5d0
files src/expr.c src/expr.h src/lwasm.h src/output.c src/parse.c
diffstat 5 files changed, 116 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/expr.c	Sat Jan 17 05:07:45 2009 +0000
+++ b/src/expr.c	Sat Jan 17 05:56:40 2009 +0000
@@ -87,6 +87,16 @@
 	return t;
 }
 
+lwasm_expr_term_t *lwasm_expr_term_create_secbase(void)
+{
+	lwasm_expr_term_t *t;
+	debug_message(10, "Creating section base term");
+	
+	t = lwasm_alloc(sizeof(lwasm_expr_term_t));
+	t -> term_type = LWASM_TERM_SECBASE;
+	return t;
+}
+
 lwasm_expr_term_t *lwasm_expr_term_create_sym(char *sym)
 {
 	lwasm_expr_term_t *t;
@@ -111,6 +121,9 @@
 		
 	case LWASM_TERM_SYM:
 		return lwasm_expr_term_create_sym(t -> symbol);
+	
+	case LWASM_TERM_SECBASE:
+		return lwasm_expr_term_create_secbase();
 		
 	default:
 		debug_message(0, "lwasm_expr_term_dup(): invalid term type %d", t -> term_type);
--- a/src/expr.h	Sat Jan 17 05:07:45 2009 +0000
+++ b/src/expr.h	Sat Jan 17 05:56:40 2009 +0000
@@ -36,6 +36,7 @@
 #define LWASM_TERM_OPER		1	// an operator
 #define LWASM_TERM_INT		2	// 32 bit signed integer
 #define LWASM_TERM_SYM		3	// symbol reference
+#define LWASM_TERM_SECBASE	4	// section base reference
 
 // operator types
 #define LWASM_OPER_NONE		0
@@ -81,6 +82,7 @@
 __expr_E__ lwasm_expr_term_t *lwasm_expr_term_create_oper(int oper);
 __expr_E__ lwasm_expr_term_t *lwasm_expr_term_create_sym(char *sym);
 __expr_E__ lwasm_expr_term_t *lwasm_expr_term_create_int(int val);
+__expr_E__ lwasm_expr_term_t *lwasm_expr_term_create_secbase(void);
 __expr_E__ lwasm_expr_term_t *lwasm_expr_term_dup(lwasm_expr_term_t *t);
 
 __expr_E__ void lwasm_expr_stack_free(lwasm_expr_stack_t *s);
--- a/src/lwasm.h	Sat Jan 17 05:07:45 2009 +0000
+++ b/src/lwasm.h	Sat Jan 17 05:56:40 2009 +0000
@@ -38,6 +38,7 @@
 {
 	int offset;						// offset into section
 	lwasm_expr_stack_t *expr;		// value definition
+	int context;					// symbol context (for local syms)
 	section_reloc_list_t *next;		// next relocation
 };
 
@@ -106,6 +107,7 @@
 	int addrset;		// set if this instruction sets the assembly address
 	int symaddr;		// set if this instruction sets a symbol addr with EQU or the like
 	int badop;			// bad operation - ignore it
+	int context;		// the symbol context for this line
 	
 	// the following are used for obj format - for external references, inter-section
 	// references, and intrasection relocations
--- a/src/output.c	Sat Jan 17 05:07:45 2009 +0000
+++ b/src/output.c	Sat Jan 17 05:56:40 2009 +0000
@@ -203,6 +203,9 @@
 	lwasm_line_t *l;
 	sectiontab_t *s;
 	lwasm_symbol_ent_t *se;
+	export_list_t *ex;
+	section_reloc_list_t *re;
+	lwasm_expr_stack_node_t *sn;			
 	
 	int i;
 	unsigned char buf[16];
@@ -246,8 +249,6 @@
 			// relocation table
 			if (l -> relocoff >= 0)
 			{
-				section_reloc_list_t *re;
-				
 				// build the relocation reference for the linker
 				re = lwasm_alloc(sizeof(section_reloc_list_t));
 				re -> next = l -> sect -> rl;
@@ -255,6 +256,7 @@
 				
 				re -> offset = l -> codeaddr + l -> relocoff;
 				re -> expr = l -> exprs[0];
+				re -> context = l -> context;
 			}
 		}
 	}
@@ -304,6 +306,100 @@
 		// flag end of local symbol table - "" is NOT an error
 		writebytes("", 1, 1, of);
 		
+		// now the exports
+		for (ex = s -> exports; ex; ex = ex -> next)
+		{
+			writebytes(ex -> sym, strlen(ex -> sym) + 1, 1, of);
+			buf[0] = (ex -> offset >> 8) & 0xff;
+			buf[1] = ex -> offset & 0xff;
+			writebytes(buf, 2, 1, of);
+		}
+		
+		// flag end of exported symbols - "" is NOT an error
+		writebytes("", 1, 1, of);
+		
+		// now output the "incomplete references"
+		// this being the most complex bit
+		for (re = s -> rl; re; re = re -> next)
+		{
+			if (re -> expr == NULL)
+			{
+				// this is an error but we'll simply ignore it
+				// and not output this expression
+				continue;
+			}
+			
+			// work through each term in the expression and output
+			// the proper equivalent to the object file
+			for (sn = re -> expr -> head; sn; sn = sn -> next)
+			{
+				switch (sn -> term -> term_type)
+				{
+				case LWASM_TERM_OPER:
+					buf[0] =  0x04;
+					buf[1] = sn -> term -> value;
+					writebytes(buf, 2, 1, of);
+					break;
+					
+				case LWASM_TERM_INT:
+					buf[0] = 0x01;
+					buf[1] = (sn -> term -> value >> 8) & 0xff;
+					buf[2] = sn -> term -> value & 0xff;
+					writebytes(buf, 3, 1, of);
+					break;
+				
+				case LWASM_TERM_SECBASE:
+					writebytes("\x05", 1, 1, of);
+					break;
+
+				case LWASM_TERM_SYM:
+					// now for the ugly part - resolve a symbol reference
+					// and determine whether it's internal, external, or
+					// a section base
+					se = lwasm_find_symbol(as, sn -> term -> symbol, re -> context);
+					if (!se)
+						se = lwasm_find_symbol(as, sn -> term -> symbol, -1);
+					if (!se || se -> flags & SYMBOL_EXTERN)
+					{
+						// not found - assume external reference
+						// found but flagged external - handle it
+						writebytes("\x02", 1, 1, of);
+						writebytes(se -> sym, strlen(se -> sym) + 1, 1, of);
+						break;
+					}
+					// a local symbol reference here
+					writebytes("\x03", 1, 1, of);
+					writebytes(se -> sym, strlen(se -> sym), 1, of);
+					if (se -> context >= 0)
+					{
+						writebytes("\x01", 1, 1, of);
+						sprintf(buf, "%d", se -> context);
+						writebytes(buf, strlen(buf), 1, of);
+					}
+					writebytes("", 1, 1, of);
+					break;
+
+				default:
+					// unrecognized term type - replace with integer 0
+					buf[0] = 0x01;
+					buf[1] = 0x00;
+					buf[2] = 0x00;
+					writebytes(buf, 3, 1, of);
+					break;
+				}
+			}
+			
+			// flag end of expressions
+			writebytes("", 1, 1, of);
+			
+			// write the offset
+			buf[0] = (re -> offset >> 8) & 0xff;
+			buf[1] = re -> offset & 0xff;
+			writebytes(buf, 2, 1, of);
+		}
+		// flag end of incomplete references list
+		writebytes("", 1, 1, of);
+		
 		// now blast out the code
 		
 		// length
--- a/src/parse.c	Sat Jan 17 05:07:45 2009 +0000
+++ b/src/parse.c	Sat Jan 17 05:56:40 2009 +0000
@@ -187,6 +187,7 @@
 	}
 	
 	l -> sect = as -> csect;
+	l -> context = as -> context;
 	
 	lwasm_free(opc);
 	if (sym)