int xreloc_relocate( xreloc xr ) { table *t = (table *) xr; int loc; int word; int mask; int err = 0; symbol *sym; symbol *rel = NULL; reloc *r; rel = findsym( t, REL_NAME ); rel->flags = FLAG_RELOCAT | FLAG_GLOBAL; rel->loc = 0; for( sym = t->syms; sym; sym = sym->next ) { if( sym->flags & FLAG_GLOBAL ) { /* symbols to be written to symbol table */ continue; } else if( sym->flags & FLAG_RELOCAT ) { /* symbols need to be relocated */ sym->flags |= FLAG_WRITTEN; for( r = sym->relocs; r; r = r->next ) { add_reloc( t, rel, r->loc, r->size, XRELOC_ABSOLUTE ); word = GETWORD( t->mem, r->loc ); mask = ( 1 << r->size ) - 1; loc = ( word & mask ) + sym->loc; if( loc & ~mask ) { fprintf( t->err, "error: relocation out of range for symbol '%s'\n", sym->name ); err = 1; } word = ( word & ~mask ) | ( loc & mask ); t->mem[r->loc] = word >> 8; t->mem[r->loc + 1] = word; } } else if( sym->loc != INV_ADDR ) { /* symbol is defined */
/* * Add a symbol to the symbol table. */ static void addsym(bool ignorethis, bool definethis, char *sym) { int symind; char *val; symind = findsym(sym); if (symind < 0) { if (nsyms >= MAXSYMS) errx(2, "too many symbols"); symind = nsyms++; } symname[symind] = sym; ignore[symind] = ignorethis; val = sym + (skipsym(sym) - sym); if (definethis) { if (*val == '=') { value[symind] = val+1; *val = '\0'; } else if (*val == '\0') value[symind] = ""; else usage(); } else { if (*val != '\0') usage(); value[symind] = NULL; } }
//deep-bindによる。シンボルが見つからなかったら登録。 //見つかったらそこに値をいれておく。 void bindsym(int symaddr, int valaddr){ int addr,num; char *name; name = symname(symaddr); if((addr=findsym(name)) == NIL){ addr = freshcell(); SET_NAME(addr,name); SET_CDR(addr,E); E = addr; } switch(GET_TAG(valaddr)){ case NUM: { SET_TAG(addr,NUM); num = GET_NUMBER(valaddr); SET_NUMBER(addr,num); break; } case SYM: { SET_TAG(addr,SYM); name = GET_NAME(valaddr); SET_NAME(addr,name); break; } case LIS: { SET_TAG(addr,LIS); SET_BIND(addr,valaddr); break; } } }
//--------eval--------------- int eval(int addr){ int res; if(atomp(addr)){ if(numberp(addr)) return(addr); if(symbolp(addr)){ res = findsym(addr); if(res == -1) error(CANT_FIND_ERR, "eval", addr); else return(res); } } else if(listp(addr)){ if((symbolp(car(addr))) &&(HAS_NAME(car(addr),"quote"))) return(cadr(addr)); if(numberp(car(addr))) error(ARG_SYM_ERR, "eval", addr); if(subrp(car(addr))) return(apply(car(addr),evlis(cdr(addr)))); if(fsubrp(car(addr))) return(apply(car(addr),cdr(addr))); if(functionp(car(addr))) return(apply(car(addr),evlis(cdr(addr)))); } error(CANT_FIND_ERR, "eval", addr); return(0); }
char *sym_find(int addr) { static char buf[256]; Sym *s; int offset; addr&=ADDRMASK; // find s=sym+findsym(addr); offset=addr-s->addr; if(offset<0 || offset>99999) { int a; a=mem_read32(addr); if(OP_OP(a)==19) { sprintf(buf,"?<patch:%i>",OP_IMM(a)); return(buf); } else return("?"); } if(offset==0) strcpy(buf,s->text); else sprintf(buf,"?%i+%s",offset,s->text); return(buf); }
int eval(int addr){ int res; if(atomp(addr)){ if(IS_NUMBER(addr)) return(addr); if(IS_SYMBOL(addr)){ res = findsym(GET_NAME(addr)); switch(GET_TAG(res)){ case NUM: return(makenum(GET_NUMBER(res))); case SYM: return(GET_BIND(res)); case LIS: return(GET_BIND(res)); } } } else{ if(HAS_NAME(car(addr),"quote")) return(cadr(addr)); if(subrp(car(addr))) return(apply(symname(car(addr)),evlis(cdr(addr)))); if(fsubrp(car(addr))) return(apply(symname(car(addr)),cdr(addr))); if(lambdap(car(addr))) return(apply(symname(car(addr)),evlis(cdr(addr)))); } return(NIL); }
Func* findfunc(uvlong pc) { Func *f; uint h; Symbol s; if(pc == 0) return nil; if(!findsym(pc, CTEXT, &s)) return nil; h = s.value % nelem(func); for(f = func[h]; f != NULL; f = f->next) if(f->s.value == s.value) return f; f = malloc(sizeof *f); memset(f, 0, sizeof *f); f->s = s; f->next = func[h]; func[h] = f; nfunc++; return f; }
/* * Function for evaluating the innermost parts of expressions, * viz. !expr (expr) number defined(symbol) symbol * We reset the constexpr flag in the last two cases. */ static Linetype eval_unary(const struct ops *ops, int *valp, const char **cpp) { const char *cp; char *ep; int sym; bool defparen; Linetype lt; cp = skipcomment(*cpp); if (*cp == '!') { debug("eval%d !", prec(ops)); cp++; lt = eval_unary(ops, valp, &cp); if (lt == LT_ERROR) return (LT_ERROR); if (lt != LT_IF) { *valp = !*valp; lt = *valp ? LT_TRUE : LT_FALSE; } } else if (*cp == '(') { cp++; debug("eval%d (", prec(ops)); lt = eval_table(eval_ops, valp, &cp); if (lt == LT_ERROR) return (LT_ERROR); cp = skipcomment(cp); if (*cp++ != ')') return (LT_ERROR); } else if (isdigit((unsigned char)*cp)) { debug("eval%d number", prec(ops)); *valp = strtol(cp, &ep, 0); if (ep == cp) return (LT_ERROR); lt = *valp ? LT_TRUE : LT_FALSE; cp = skipsym(cp); } else if (strncmp(cp, "defined", 7) == 0 && endsym(cp[7])) { cp = skipcomment(cp+7); debug("eval%d defined", prec(ops)); if (*cp == '(') { cp = skipcomment(cp+1); defparen = true; } else { defparen = false; } sym = findsym(cp); if (sym < 0) { lt = LT_IF; } else { *valp = (value[sym] != NULL); lt = *valp ? LT_TRUE : LT_FALSE; } cp = skipsym(cp); cp = skipcomment(cp); if (defparen && *cp++ != ')') return (LT_ERROR); constexpr = false; } else if (!endsym(*cp)) {
int fsubrp(int addr){ int val; val = findsym(addr); if(val != -1) return(IS_FSUBR(val)); else return(0); }
int lambdap(int addr){ int val; val = findsym(addr); if(val != 0) return(IS_LAMBDA(val)); else return(0); }
int subrp(int addr){ int val; val = findsym(addr); if(val != 0) return(IS_SUBR(val)); else return(0); }
int functionp(int addr){ int val; val = findsym(addr); if(val != -1) return(IS_FUNC(val)); else return(0); }
static int scanprec( unsigned used, a_sym **precsym ) { if( token != PREC ) return( FALSE ); if( scan( used ) != IDENTIFIER || !(*precsym = findsym( buf )) || !(*precsym)->token ) { msg( "Expecting a token after %prec.\n" ); } scan( used ); return( TRUE ); }
// XXX print dwarf static void print_ip(uint64_t ip, uint64_t cr3) { struct sym *sym = findsym(ip, cr3); if (sym) { printf("%s", sym->name); if (ip - sym->val > 0) printf("+%ld", ip - sym->val); } else printf("%lx", ip); }
FILE * fincludegets(char *buf, int size, FILE *fp) { char name[MAXPATHLEN]; FILE *nfp=NULL; char *p; int ch; if (fp == NULL) return(NULL); if (fgets(buf, size, fp) == NULL) { *buf = '\0'; fclose(fp); fp = popfp(); return (fp); } if ((p = strchr(buf, '\n')) != NULL) *p = '\0'; else { /* Flush this line */ while ((ch = fgetc(fp)) != '\n' && ch != EOF); if (ch == EOF) { *buf = '\0'; fclose(fp); fp = popfp(); return(fp); } } switch (tokenscpp(buf, name)) { case T_INCLUDE: *buf = '\0'; if ((nfp = fopen(name, "r")) != NULL) { pushfp(fp); fp = nfp; } break; case T_DEFINE: addsym(name); break; case T_IFNDEF: if (findsym(name)) { fclose(fp); fp = popfp(); *buf = '\0'; } break; case T_ENDIF: *buf = '\0'; break; default: break; } return (fp); }
METAMOD_PLUGIN *_GetPluginPtr(const char *path, int fail_api) { METAMOD_FN_ORIG_LOAD fn; METAMOD_PLUGIN *pl; int ret; if (!(g_hCore=openlib(path))) { #if defined __linux__ || defined __APPLE__ UTIL_Format(s_FailPlugin.error_buffer, sizeof(s_FailPlugin.error_buffer), "%s", dlerror()); #else DWORD err = GetLastError(); if (FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), s_FailPlugin.error_buffer, sizeof(s_FailPlugin.error_buffer), NULL) == 0) { UTIL_Format(s_FailPlugin.error_buffer, sizeof(s_FailPlugin.error_buffer), "unknown error %x", err); } #endif s_FailPlugin.fail_version = fail_api; return (METAMOD_PLUGIN *)&s_FailPlugin; } if (!(fn=(METAMOD_FN_ORIG_LOAD)findsym(g_hCore, "CreateInterface"))) { goto error; } pl = (METAMOD_PLUGIN *)fn(METAMOD_PLAPI_NAME, &ret); if (!pl) { goto error; } return pl; error: closelib(g_hCore); g_hCore = NULL; return NULL; }
void xreloc_global( xreloc xr, char *name ) { table *t = (table *) xr; symbol *sym; assert( t ); assert( name ); sym = findsym( t, name ); assert( sym ); sym->flags |= FLAG_GLOBAL; }
void sym_del(int addr) { Sym *s; // find s=sym+findsym(addr); if(s->addr==addr) { memmove(s,s+1,SYMSIZE-1-(s-sym)); symnum--; } }
static int i386trace(uvlong pc, uvlong sp, uvlong link) { int i; uvlong osp; Symbol s, f; char buf[128]; USED(link); i = 0; osp = 0; while(findsym(pc, CTEXT, &s)) { symoff(buf, sizeof buf, pc, CANY); fmt(buf, pc); //XXX s.value &= ~(uintptr)0; if(pc != s.value) { /* not at first instruction */ if(findlocal(&s, FRAMENAME, &f) == 0) break; sp += f.value-mach->szaddr; }else if(strcmp(s.name, "forkret") == 0){ //XXX print("//passing interrupt frame; last pc found at sp=%#llux\n", osp); sp += 15 * mach->szaddr; /* pop interrupt frame */ } pc = getval(sp); //XXX if(pc == 0 && strcmp(s.name, "forkret") == 0){ sp += 3 * mach->szaddr; /* pop iret eip, cs, eflags */ print("//guessing call through invalid pointer, try again at sp=%#llux\n", sp); s.name = ""; pc = getval(sp); } if(pc == 0) { print("//didn't find pc at sp=%#llux, last pc found at sp=%#llux\n", sp, osp); break; } osp = sp; sp += mach->szaddr; //XXX if(strcmp(s.name, "forkret") == 0) sp += 2 * mach->szaddr; /* pop iret cs, eflags */ if(++i > 40) break; } return i; }
int fsubrp(int addr){ int symaddr; symaddr = findsym(symname(addr)); if(symaddr == NIL) return(0); else { if((IS_FUNC(symaddr)) && (IS_FSUBR(symaddr))) return(1); else return(0); } }
int lambdap(int addr){ int symaddr; symaddr = findsym(symname(addr)); if(symaddr == NIL) return(0); else { if((IS_FUNC(symaddr)) && (IS_LAMBDA(symaddr))) return(1); else return(0); } }
uint32_t eval(int p, int q, bool *success) { //Log("EVAL %d %d",p, q); if (p > q) { //*success = false; //printf("BAD EXPRESSION\n"); return 0; } else if (p == q) { uint32_t ret; char buf[32]; int i; switch (tokens[p].type) { case NUM: sscanf(tokens[p].str, "%u", &ret); return ret; case HEXNUM: sscanf(tokens[p].str, "%X", &ret); return ret; case VAR: return findsym(tokens[p].str); case REG: memset(buf, 0, sizeof(buf)); sscanf(tokens[p].str + 1, "%s", buf); for (i = R_EAX; i <= R_EDI; i++) { if (strcmp(buf, regsl[i]) == 0) return cpu.gpr[i]._32; } for (i = R_AX; i <= R_DI; i++) { if (strcmp(buf, regsw[i]) == 0) return cpu.gpr[i]._16; } for (i = R_AL; i <= R_BH; i++) { if (strcmp(buf, regsb[i]) == 0) return cpu.gpr[i % 4]._8[i / 4]; } for(i = E_CF; i <= E_VM; i++) { if(strcmp(buf, regeflags[i]) == 0) return (cpu.EFLAGS & (1 << i)) >> i; } if(strcmp(buf, "eip") == 0) return cpu.eip; if(strcmp(buf, "eflags") == 0) return cpu.EFLAGS; default: Assert(0,"tokens[%d].type = %d",p,tokens[p].type); } }
static void addsym(const char *name) { int i; if (!findsym(name)) for (i=0; i < MAXSYMS; i++) { if (symtable[i] == NULL) { symtable[i] = strdup(name); if (symtable[i] == NULL) errx(1, "malloc error in addsym"); return; } } errx(1, "symbol table full\n"); }
/* Get symbol, add to table if not present */ Sym* getsym(word name) { Sym *s; s = findsym(name); if(s == nil){ for(s = symtab; s < &symtab[MAXSYM]; s++) if(s->name == 0) goto found; panic("symbol table full"); found: s->name = name; s->type = Undef; s->v = (Value){ 0, 0 }; } return s; }
static int scanambig( unsigned used, a_SR_conflict_list **list ) { int absorbed_something; unsigned index; a_sym *sym; a_SR_conflict *am; a_SR_conflict_list *en; absorbed_something = FALSE; for( ;; ) { /* syntax is "%ambig <number> <token>" */ /* token has already been scanned by scanprec() */ if( token != AMBIG ) { break; } if( scan( used ) != NUMBER || value < 0 ) { msg( "Expecting a non-negative number after %ambig.\n" ); break; } index = value; if( scan( used ) != IDENTIFIER ) { msg( "Expecting a token name after %ambig <number>.\n" ); break; } sym = findsym( buf ); if( sym == NULL ) { msg( "Unknown token specified in %ambig directive.\n" ); break; } if( sym->token == 0 ) { msg( "Non-terminal specified in %ambig directive.\n" ); break; } scan( used ); absorbed_something = TRUE; am = make_unique_ambiguity( sym, index ); en = MALLOC( 1, a_SR_conflict_list ); en->next = *list; en->thread = am->thread; en->pro = NULL; en->conflict = am; am->thread = en; *list = en; } return( absorbed_something ); }
int xreloc_symbol( xreloc xr, int loc, char *name ) { table *t = (table *) xr; symbol *sym; assert( t ); assert( name ); sym = findsym( t, name ); assert( sym ); if( sym->loc != INV_ADDR ) { fprintf( t->err, "error: symbol '%s' is redefined\n", name ); return 0; } sym->loc = loc; return 1; }
//--------eval--------------- int eval(int addr){ int res; //ctrl+cによる割り込みがあった場合 if(exit_flag == 1){ exit_flag = 0; P = addr; //後で調べられるように退避 printf("exit eval by CTRL_C_EVENT\n"); fflush(stdout); longjmp(buf,1); } if(atomp(addr)){ if(numberp(addr)) return(addr); if(symbolp(addr)){ res = findsym(addr); if(res == 0) error(CANT_FIND_ERR, "eval", addr); else switch(GET_TAG(res)){ case NUM: return(res); case SYM: return(res); case LIS: return(res); case SUBR: return(res); case FSUBR: return(res); case LAMBDA:return(GET_BIND(res)); } } } else if(listp(addr)){ if((symbolp(car(addr))) &&(HAS_NAME(car(addr),"quote"))) return(cadr(addr)); if(numberp(car(addr))) error(ARG_SYM_ERR, "eval", addr); if(subrp(car(addr))) return(apply(car(addr),evlis(cdr(addr)))); if(fsubrp(car(addr))) return(apply(car(addr),cdr(addr))); if(lambdap(car(addr))) return(apply(car(addr),evlis(cdr(addr)))); } error(CANT_FIND_ERR, "eval", addr); }
int xreloc_reloc( xreloc xr, int loc, int size, char *name, unsigned char flags ) { table *t = (table *) xr; symbol *sym; assert( t ); assert( name ); if( loc == INV_ADDR ) { fprintf( stderr, "error: invalid address '%x', object may be too big\n", INV_ADDR ); return 0; } sym = findsym( t, name ); assert( sym ); add_reloc( t, sym, loc, size, flags ); return 1; }
static int rtrace(uvlong pc, uvlong sp, uvlong link) { Symbol s, f; char buf[128]; uvlong oldpc; int i; i = 0; while(findsym(pc, CTEXT, &s)) { if(pc == s.value) /* at first instruction */ f.value = 0; else if(findlocal(&s, FRAMENAME, &f) == 0) break; symoff(buf, sizeof buf, pc, CANY); fmt(buf, pc); oldpc = pc; if(s.type == 'L' || s.type == 'l' || pc <= s.value+mach->pcquant){ if(link == 0) fprint(2, "%s: need to supply a valid link register\n", argv0); pc = link; }else{ pc = getval(sp); if(pc == 0) break; } if(pc == 0 || (pc == oldpc && f.value == 0)) break; sp += f.value; if(++i > 40) break; } return i; }
int apply(char *symname, int args){ int symaddr,lamlis,body,res; symaddr = findsym(symname); if(symaddr == NIL) return(NIL); else { switch(GET_FTYPE(symaddr)){ case SUBR: return((heap[symaddr].subr)(args)); case FSUBR: return((heap[symaddr].subr)(args)); case LAMBDA: { lamlis = car(heap[symaddr].bind); body = cdr(heap[symaddr].bind); bind(lamlis,args); while(!(IS_NIL(body))){ res = eval(car(body)); body = cdr(body); } unbind(); return(res); } } } }