Mercurial > hg-old > index.cgi
diff lwlink/link.c @ 171:d610b8aef91b
Added LWAR skeleton
author | lost |
---|---|
date | Sun, 01 Mar 2009 19:37:03 +0000 |
parents | 106c2fe3c9d9 |
children | 0395e6fd67e9 |
line wrap: on
line diff
--- a/lwlink/link.c Sun Mar 01 00:53:21 2009 +0000 +++ b/lwlink/link.c Sun Mar 01 19:37:03 2009 +0000 @@ -35,6 +35,84 @@ struct section_list *sectlist = NULL; int nsects = 0; +void check_section_name(char *name, int *base, fileinfo_t *fn) +{ + int sn; + for (sn = 0; sn < fn -> nsections; sn++) + { + if (!strcmp(name, fn -> sections[sn].name)) + { + // we have a match + sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1)); + sectlist[nsects].ptr = &(fn -> sections[sn]); + + fn -> sections[sn].processed = 1; + fn -> sections[sn].loadaddress = *base; + *base += fn -> sections[sn].codesize; + nsects++; + } + } + for (sn = 0; sn < fn -> nsubs; fn++) + { + check_section_name(name, base, fn -> subs[sn]); + } +} + +void add_matching_sections(char *name, int yesflags, int noflags, int *base); +void check_section_flags(int yesflags, int noflags, int *base, fileinfo_t *fn) +{ + int sn; + for (sn = 0; sn < fn -> nsections; sn++) + { + // ignore if the noflags tell us to + if (noflags && (fn -> sections[sn].flags & noflags)) + continue; + // ignore unless the yesflags tell us not to + if (yesflags && (fn -> sections[sn].flags & yesflags == 0)) + continue; + // ignore it if already processed + if (fn -> sections[sn].processed) + continue; + + // we have a match - now collect *all* sections of the same name! + add_matching_sections(fn -> sections[sn].name, 0, 0, base); + + // and then continue looking for sections + } + for (sn = 0; sn < fn -> nsubs; fn++) + { + check_section_flags(yesflags, noflags, base, fn -> subs[sn]); + } +} + + + +void add_matching_sections(char *name, int yesflags, int noflags, int *base) +{ + int fn; + if (name) + { + // named section + // look for all instances of a section by the specified name + // and resolve base addresses and add to the list + for (fn = 0; fn < ninputfiles; fn++) + { + check_section_name(name, base, inputfiles[fn]); + } + } + else + { + // wildcard section + // named section + // look for all instances of a section by the specified name + // and resolve base addresses and add to the list + for (fn = 0; fn < ninputfiles; fn++) + { + check_section_flags(yesflags, noflags, base, inputfiles[fn]); + } + } +} + // work out section load order and resolve base addresses for each section // make a list of sections to load in order void resolve_sections(void) @@ -44,41 +122,12 @@ for (ln = 0; ln < linkscript.nlines; ln++) { -// printf("Linker script line %d: '%s', %04X, %d, %d\n", ln, linkscript.lines[ln].sectname, linkscript.lines[ln].loadat, linkscript.lines[ln].yesflags, linkscript.lines[ln].noflags); + if (linkscript.lines[ln].loadat >= 0) + laddr = linkscript.lines[ln].loadat; + add_matching_sections(linkscript.lines[ln].sectname, linkscript.lines[ln].yesflags, linkscript.lines[ln].noflags, &laddr); + if (linkscript.lines[ln].sectname) { - int f = 0; - // named section - // look for all instances of a section by the specified name - // and resolve base addresses and add to the list - for (fn = 0; fn < ninputfiles; fn++) - { - for (sn = 0; sn < inputfiles[fn] -> nsections; sn++) - { -// printf(" Considering %s:%s\n", inputfiles[fn]->filename, inputfiles[fn]->sections[sn].name); - if (!strcmp(linkscript.lines[ln].sectname, inputfiles[fn] -> sections[sn].name)) - { - // we have a match - sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1)); - sectlist[nsects].ptr = &(inputfiles[fn] -> sections[sn]); - - inputfiles[fn] -> sections[sn].processed = 1; - if (!f && linkscript.lines[ln].loadat >= 0) - { - f = 1; - sectlist[nsects].forceaddr = 1; - laddr = linkscript.lines[ln].loadat; - } - else - { - sectlist[nsects].forceaddr = 0; - } - inputfiles[fn] -> sections[sn].loadaddress = laddr; - laddr += inputfiles[fn] -> sections[sn].codesize; - nsects++; - } - } - } } else { @@ -141,6 +190,39 @@ // theoretically, all the base addresses are set now } +lw_expr_stack_t *find_external_sym_recurse(char *sym, fileinfo_t *fn) +{ + int sn; + lw_expr_stack_t *r; + lw_expr_term_t *term; + symtab_t *se; + int val; + + for (sn = 0; sn < fn -> nsections; sn++) + { + for (se = fn -> sections[sn].exportedsyms; se; se = se -> next) + { + if (!strcmp(sym, se -> sym)) + { + val = se -> offset + fn -> sections[sn].loadaddress; + r = lw_expr_stack_create(); + term = lw_expr_term_create_int(val & 0xffff); + lw_expr_stack_push(r, term); + lw_expr_term_free(term); + return r; + } + } + } + + for (sn = 0; sn < fn -> nsubs; sn++) + { + r = find_external_sym_recurse(sym, fn -> subs[sn]); + if (r) + return r; + } + return NULL; +} + // 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 @@ -151,7 +233,8 @@ int val = 0, i, fn; lw_expr_stack_t *s; symtab_t *se; - + fileinfo_t *fp; + if (symtype == 1) { // local symbol @@ -190,19 +273,18 @@ { // external symbol // read all files in order until found (or not found) + for (fp = sect -> file; fp; fp = fp -> parent) + { + s = find_external_sym_recurse(sym, fp); + if (s) + return s; + } + 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; - } - } - } + s = find_external_sym_recurse(sym, inputfiles[fn]); + if (s) + return s; } if (sect) {