real compute(F_NODE *formula, SYM_PAIR sym_value_map[], int sym_num) { if (formula->node_type == NODE_TYPE_NUM) { return formula->num; } if (formula->node_type == NODE_TYPE_SYM) { return get_sym_value(formula->sym, sym_value_map, sym_num); } int i; real para[MAX_CHILD_NODE]; if (formula->node_type == NODE_TYPE_FUN) { for (i = 0; i < MAX_CHILD_NODE; ++i) { if (formula->child[i] == NULL) { break; } para[i] = compute(formula->child[i], sym_value_map, sym_num); } return formula->fun(i, para); } // error return 0.0; }
static taddr tos_sym_value(symbol *sym,int textbased) { taddr val = get_sym_value(sym); /* all sections form a contiguous block, so add section offset */ if (textbased && sym->type==LABSYM && sym->sec!=NULL) val += secoffs[sym->sec->idx]; return val; }
static int tos_initwrite(section *sec,symbol *sym) { int nsyms = 0; int i; /* find exactly one .text, .data and .bss section for a.out */ sections[_TEXT] = sections[_DATA] = sections[_BSS] = NULL; secsize[_TEXT] = secsize[_DATA] = secsize[_BSS] = 0; for (; sec; sec=sec->next) { /* section size is assumed to be in in (sec->pc - sec->org), otherwise we would have to calculate it from the atoms and store it there */ if ((sec->pc - sec->org) > 0 || (sec->flags & HAS_SYMBOLS)) { i = get_sec_type(sec); if (!sections[i]) { sections[i] = sec; secsize[i] = (get_sec_size(sec) + SECT_ALIGN - 1) / SECT_ALIGN * SECT_ALIGN; sec->idx = i; /* section index 0:text, 1:data, 2:bss */ } else output_error(7,sec->name); } } max_relocs_per_atom = 1; secoffs[_TEXT] = 0; secoffs[_DATA] = secsize[_TEXT] + balign(secsize[_TEXT],SECT_ALIGN); secoffs[_BSS] = secoffs[_DATA] + secsize[_DATA] + balign(secsize[_DATA],SECT_ALIGN); /* define small data base as .data+32768 @@@FIXME! */ sdabase = secoffs[_DATA] + 0x8000; /* count symbols */ for (; sym; sym=sym->next) { /* ignore symbols preceded by a '.' and internal symbols */ if (*sym->name!='.' && *sym->name!=' ') { if (!(sym->flags & (VASMINTERN|COMMON)) && sym->type == LABSYM) { nsyms++; if ((strlen(sym->name) > DRI_NAMELEN) && tos_hisoft_dri) nsyms++; /* extra symbol for long name */ } } else { if (!strcmp(sym->name," TOSFLAGS")) { if (tosflags == 0) /* not defined by command line? */ tosflags = (int)get_sym_value(sym); } sym->flags |= VASMINTERN; } } return no_symbols ? 0 : nsyms; }
static unsigned long aout_convert_rlist(int be,atom *a,int secid, struct list *rlst,taddr pc, unsigned long (*getrinfo)(rlist *,int,char *,int)) /* convert all of an atom's relocs into a.out relocations */ { unsigned long rsize = 0; rlist *rl; if (a->type == DATA) rl = a->content.db->relocs; else if (a->type == SPACE) rl = a->content.sb->relocs; else rl = NULL; if (!rl) return 0; /* no relocs or not the right atom type */ do { nreloc *r = (nreloc *)rl->reloc; symbol *refsym = r->sym; taddr val = get_sym_value(refsym); taddr add = nreloc_real_addend(r); #if SDAHACK int based = getrinfo(rl,-1,sections[secid]->name,be) != 0; #endif if (refsym->type == LABSYM) { /* this is a local relocation */ int rsecid = refsym->sec->idx; aout_addreloclist(rlst,pc+(r->offset>>3),sectype[rsecid], getrinfo(rl,0,sections[secid]->name,be), be); #if SDAHACK if (!based) /* @@@ 'based' does not really happen in Unix */ #endif val += secoffs[rsecid]; rsize += sizeof(struct relocation_info); } else if (refsym->type == IMPORT) { /* this is an external symbol reference */ int symidx; if ((symidx = aout_findsym(refsym->name,be)) == -1) symidx = aout_addsym(refsym->name,0,0,0,N_UNDF|N_EXT,0,be); aout_addreloclist(rlst,pc+(r->offset>>3),symidx, getrinfo(rl,1,sections[secid]->name,be), be); rsize += sizeof(struct relocation_info); }
static void aout_symconvert(symbol *sym,int symbind,int syminfo,int be) /* convert vasm symbol into a.out symbol(s) */ { taddr val = get_sym_value(sym); taddr size = get_sym_size(sym); int ext = (symbind == BIND_GLOBAL) ? N_EXT : 0; int type = 0; if (TYPE(sym) == TYPE_SECTION) { return; /* section symbols are ignored in a.out! */ } else if (TYPE(sym) == TYPE_FILE) { type = N_FN | N_EXT; /* special case: file name symbol */ size = 0; } else { if (sym->flags & COMMON) { /* common symbol */ #if 0 /* GNU binutils prefers N_UNDF with val!=0 instead of N_COMM! */ type = N_COMM | ext; #else type = N_UNDF | N_EXT; #endif } else if (sym->flags & WEAK) { /* weak symbol */ switch (sym->type) { case LABSYM: type=secweak[sym->sec->idx]; break; case IMPORT: type=N_WEAKU; break; case EXPRESSION: type=N_WEAKA; break; default: ierror(0); break; } } else if (sym->sec) { /* address symbol */ type = sectype[sym->sec->idx] | ext; val += secoffs[sym->sec->idx]; /* a.out requires to add sec. offset */ } else if (sym->type==EXPRESSION) { if (sym->flags & EXPORT) { /* absolute symbol */ type = N_ABS | ext; } else return; /* ignore local expressions */ } /* @@@ else if (indirect symbols?) { aout_addsym(sym->name,0,symbind,0,N_INDR|ext,0,be); aout_addsym(sym->indir_name,0,0,0,N_UNDF|N_EXT,0,be); return; }*/ else ierror(0); } aout_addsym(sym->name,val,symbind,syminfo,type,0,be); if (size) { /* append N_SIZE symbol declaring the previous symbol's size */ aout_addsym(sym->name,size,symbind,syminfo,N_SIZE,0,be); } }