# HG changeset patch # User lost # Date 1232171800 0 # Node ID 718998b673ee5aefb14228244ea518e25e612ac6 # Parent 6097cb1486f83032c5c81114247ee9fcc31a4cf9 Added incomplete references to object output and added support for section base terms in expression handler diff -r 6097cb1486f8 -r 718998b673ee src/expr.c --- 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); diff -r 6097cb1486f8 -r 718998b673ee src/expr.h --- 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); diff -r 6097cb1486f8 -r 718998b673ee src/lwasm.h --- 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 diff -r 6097cb1486f8 -r 718998b673ee src/output.c --- 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 diff -r 6097cb1486f8 -r 718998b673ee src/parse.c --- 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)