# HG changeset patch # User lost # Date 1232518448 0 # Node ID 36ce328df3c33fe40fb786af93ff4129bae49263 # Parent 8bc00221ae89f36c9f06f2360fbc0b8c98349aaa resolve incomplete references done diff -r 8bc00221ae89 -r 36ce328df3c3 lwlink/trunk/src/link.c --- 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 #include +#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; + } + } +} diff -r 8bc00221ae89 -r 36ce328df3c3 lwlink/trunk/src/lwlink.h --- 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 }; diff -r 8bc00221ae89 -r 36ce328df3c3 lwlink/trunk/src/readfiles.c --- 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: