diff src/output.c @ 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 6460a1fb5f1f
children
line wrap: on
line diff
--- 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