/* Add a never-delete-me Spec. This is a bit of a kludge. On the assumption that this is called only at startup, only handle the case where topSpecs is completely empty, or if it isn't, it has just one entry and that is the one with NULL seginfo -- that is the entry that holds these initial specs. */ __attribute__((unused)) /* not used on all platforms */ static void add_hardwired_spec ( HChar* sopatt, HChar* fnpatt, Addr to_addr ) { Spec* spec = symtab_alloc(sizeof(Spec)); vg_assert(spec); if (topSpecs == NULL) { topSpecs = symtab_alloc(sizeof(TopSpec)); vg_assert(topSpecs); topSpecs->next = NULL; topSpecs->seginfo = NULL; topSpecs->specs = NULL; topSpecs->mark = False; } vg_assert(topSpecs != NULL); vg_assert(topSpecs->next == NULL); vg_assert(topSpecs->seginfo == NULL); spec->from_sopatt = sopatt; spec->from_fnpatt = fnpatt; spec->to_addr = to_addr; spec->isWrap = False; spec->mark = False; /* not significant */ spec->next = topSpecs->specs; topSpecs->specs = spec; }
fp_subdir_ty * fp_find_subdir(string_ty *dirname, int ok_to_read) { fp_subdir_ty *sdp; /* * Most of the time, we have already polled this one before, * so do a quick lookup and see. */ trace(("fp_find_subdir(dirname = \"%s\")\n{\n", dirname->str_text)); if (!subdir_stp) { static string_ty *dot; subdir_stp = symtab_alloc(10); subdir_stp->reap = subdir_reap; /* * Read dot (the current directory) immediately. * This primes the cache with all the things that were * found to be read-only on previous runs. */ if (!dot) dot = str_from_c("."); sdp = fp_subdir_new(dot); symtab_assign(subdir_stp, dot, sdp); fp_subdir_read(sdp); } sdp = symtab_query(subdir_stp, dirname); if (!sdp) { /* * It's a new one, we must allocate it. */ sdp = fp_subdir_new(dirname); symtab_assign(subdir_stp, dirname, sdp); } if (ok_to_read && sdp->need_to_read) { /* * Read in the cache file from the directory, * if it exists. This causes a number of * fp_find_update calls (see below), one for * each entry. */ fp_subdir_read(sdp); } trace(("return %08lX;\n", (long)sdp)); trace(("}\n")); return sdp; }
static symtab_ty * get_main_stp(void) { if (!main_stp) { main_stp = symtab_alloc(100); /* * DO NOT set main_stp->reap * as this will be done by fp_subdir_delete */ quit_handler_prio(fp_find_flush); } return main_stp; }
fp_subdir_ty * fp_subdir_new(string_ty *path) { fp_subdir_ty *this; trace(("fp_subdir_new(path = \"%s\")\n{\n", path->str_text)); this = mem_alloc(sizeof(fp_subdir_ty)); this->stp = symtab_alloc(5); this->stp->reap = reap; this->path = str_copy(path); this->dirty = 0; this->cache_in_dot = 0; this->need_to_read = 1; trace(("return %08lX;\n", (long)this)); trace(("}\n")); return this; }
static recipe_list_ty * cook_implicit_find(string_ty *filename) { recipe_list_ty *rlp; if (!implicit_stp) { implicit_stp = symtab_alloc(200); implicit_stp->reap = explicit_reap; } rlp = symtab_query(implicit_stp, filename); if (!rlp) { rlp = recipe_list_new(); symtab_assign(implicit_stp, filename, rlp); } return rlp; }
static int reserved(string_ty *s) { typedef struct table_ty table_ty; struct table_ty { char *name; int token; }; static table_ty table[] = { { "override", OVERRIDE }, { "include", INCLUDE2 }, { "-include", INCLUDE3 }, { ".include", INCLUDE }, { "vpath", VPATH }, { "VPATH", VPATH2 }, { "ifdef", IF }, { "ifndef", IF }, { "ifeq", IF }, { "ifneq", IF }, { "else", ELSE }, { "endif", ENDIF }, { "endef", ENDDEF }, { "define", DEFINE }, { "export", EXPORT }, { "unexport", UNEXPORT }, }; static symtab_ty *symtab; int *data; string_ty *name; char *cp; if (!symtab) { table_ty *tp; symtab = symtab_alloc(SIZEOF(table)); for (tp = table; tp < ENDOF(table); ++tp) { name = str_from_c(tp->name); symtab_assign(symtab, name, &tp->token); str_free(name); } } cp = strchr(s->str_text, '('); if (cp) { name = str_n_from_c(s->str_text, cp - s->str_text); data = symtab_query(symtab, name); str_free(name); } else data = symtab_query(symtab, s); if (data) return *data; return 0; }
void VG_(redir_notify_new_SegInfo)( SegInfo* newsi ) { Bool ok, isWrap; Int i, nsyms; Spec* specList; Spec* spec; TopSpec* ts; TopSpec* newts; HChar* sym_name; Addr sym_addr, sym_toc; HChar demangled_sopatt[N_DEMANGLED]; HChar demangled_fnpatt[N_DEMANGLED]; Bool check_ppcTOCs = False; const UChar* newsi_soname; # if defined(VG_PLAT_USES_PPCTOC) check_ppcTOCs = True; # endif vg_assert(newsi); newsi_soname = VG_(seginfo_soname)(newsi); vg_assert(newsi_soname != NULL); /* stay sane: we don't already have this. */ for (ts = topSpecs; ts; ts = ts->next) vg_assert(ts->seginfo != newsi); /* scan this SegInfo's symbol table, pulling out and demangling any specs found */ specList = NULL; /* the spec list we're building up */ nsyms = VG_(seginfo_syms_howmany)( newsi ); for (i = 0; i < nsyms; i++) { VG_(seginfo_syms_getidx)( newsi, i, &sym_addr, &sym_toc, NULL, &sym_name ); ok = VG_(maybe_Z_demangle)( sym_name, demangled_sopatt, N_DEMANGLED, demangled_fnpatt, N_DEMANGLED, &isWrap ); if (!ok) { /* It's not a full-scale redirect, but perhaps it is a load-notify fn? Let the load-notify department see it. */ handle_maybe_load_notifier( newsi_soname, sym_name, sym_addr ); continue; } if (check_ppcTOCs && sym_toc == 0) { /* This platform uses toc pointers, but none could be found for this symbol, so we can't safely redirect/wrap to it. Just skip it; we'll make a second pass over the symbols in the following loop, and complain at that point. */ continue; } spec = symtab_alloc(sizeof(Spec)); vg_assert(spec); spec->from_sopatt = symtab_strdup(demangled_sopatt); spec->from_fnpatt = symtab_strdup(demangled_fnpatt); vg_assert(spec->from_sopatt); vg_assert(spec->from_fnpatt); spec->to_addr = sym_addr; spec->isWrap = isWrap; /* check we're not adding manifestly stupid destinations */ vg_assert(is_plausible_guest_addr(sym_addr)); spec->next = specList; spec->mark = False; /* not significant */ specList = spec; } if (check_ppcTOCs) { for (i = 0; i < nsyms; i++) { VG_(seginfo_syms_getidx)( newsi, i, &sym_addr, &sym_toc, NULL, &sym_name ); ok = VG_(maybe_Z_demangle)( sym_name, demangled_sopatt, N_DEMANGLED, demangled_fnpatt, N_DEMANGLED, &isWrap ); if (!ok) /* not a redirect. Ignore. */ continue; if (sym_toc != 0) /* has a valid toc pointer. Ignore. */ continue; for (spec = specList; spec; spec = spec->next) if (0 == VG_(strcmp)(spec->from_sopatt, demangled_sopatt) && 0 == VG_(strcmp)(spec->from_fnpatt, demangled_fnpatt)) break; if (spec) /* a redirect to some other copy of that symbol, which does have a TOC value, already exists */ continue; /* Complain */ VG_(message)(Vg_DebugMsg, "WARNING: no TOC ptr for redir/wrap to %s %s", demangled_sopatt, demangled_fnpatt); } } /* Ok. Now specList holds the list of specs from the SegInfo. Build a new TopSpec, but don't add it to topSpecs yet. */ newts = symtab_alloc(sizeof(TopSpec)); vg_assert(newts); newts->next = NULL; /* not significant */ newts->seginfo = newsi; newts->specs = specList; newts->mark = False; /* not significant */ /* We now need to augment the active set with the following partial cross product: (1) actives formed by matching the new specs in specList against all symbols currently listed in topSpecs (2) actives formed by matching the new symbols in newsi against all specs currently listed in topSpecs (3) actives formed by matching the new symbols in newsi against the new specs in specList This is necessary in order to maintain the invariant that Actives contains all bindings generated by matching ALL specs in topSpecs against ALL symbols in topSpecs (that is, a cross product of ALL known specs against ALL known symbols). */ /* Case (1) */ for (ts = topSpecs; ts; ts = ts->next) { if (ts->seginfo) generate_and_add_actives( specList, newts, ts->seginfo, ts ); } /* Case (2) */ for (ts = topSpecs; ts; ts = ts->next) { generate_and_add_actives( ts->specs, ts, newsi, newts ); } /* Case (3) */ generate_and_add_actives( specList, newts, newsi, newts ); /* Finally, add the new TopSpec. */ newts->next = topSpecs; topSpecs = newts; if (VG_(clo_trace_redir)) show_redir_state("after VG_(redir_notify_new_SegInfo)"); }