Mercurial > hg-old > index.cgi
diff src/link.c @ 302:eff969272fb9
resolve incomplete references done
author | lost |
---|---|
date | Wed, 21 Jan 2009 06:14:08 +0000 |
parents | 376cc55361c7 |
children | 13272197d278 |
line wrap: on
line diff
--- a/src/link.c Wed Jan 21 05:45:25 2009 +0000 +++ b/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; + } + } +}