DECLSPEC_HIDDEN BOOL coff_process_info(const struct msc_debug_info* msc_dbg) { const IMAGE_AUX_SYMBOL* aux; const IMAGE_COFF_SYMBOLS_HEADER* coff; const IMAGE_LINENUMBER* coff_linetab; const IMAGE_LINENUMBER* linepnt; const char* coff_strtab; const IMAGE_SYMBOL* coff_sym; const IMAGE_SYMBOL* coff_symbols; struct CoffFileSet coff_files; int curr_file_idx = -1; unsigned int i; int j; int k; int l; int linetab_indx; const char* nampnt; int naux; BOOL ret = FALSE; ULONG64 addr; TRACE("Processing COFF symbols...\n"); assert(sizeof(IMAGE_SYMBOL) == IMAGE_SIZEOF_SYMBOL); assert(sizeof(IMAGE_LINENUMBER) == IMAGE_SIZEOF_LINENUMBER); coff_files.files = NULL; coff_files.nfiles = coff_files.nfiles_alloc = 0; coff = (const IMAGE_COFF_SYMBOLS_HEADER*)msc_dbg->root; coff_symbols = (const IMAGE_SYMBOL*)((const char *)coff + coff->LvaToFirstSymbol); coff_linetab = (const IMAGE_LINENUMBER*)((const char *)coff + coff->LvaToFirstLinenumber); coff_strtab = (const char*)(coff_symbols + coff->NumberOfSymbols); linetab_indx = 0; for (i = 0; i < coff->NumberOfSymbols; i++) { coff_sym = coff_symbols + i; naux = coff_sym->NumberOfAuxSymbols; if (coff_sym->StorageClass == IMAGE_SYM_CLASS_FILE) { curr_file_idx = coff_add_file(&coff_files, msc_dbg->module, (const char*)(coff_sym + 1)); TRACE("New file %s\n", (const char*)(coff_sym + 1)); i += naux; continue; } if (curr_file_idx < 0) { assert(coff_files.nfiles == 0 && coff_files.nfiles_alloc == 0); curr_file_idx = coff_add_file(&coff_files, msc_dbg->module, "<none>"); TRACE("New file <none>\n"); } /* * This guy marks the size and location of the text section * for the current file. We need to keep track of this so * we can figure out what file the different global functions * go with. */ if (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC && naux != 0 && coff_sym->Type == 0 && coff_sym->SectionNumber == 1) { aux = (const IMAGE_AUX_SYMBOL*) (coff_sym + 1); if (coff_files.files[curr_file_idx].linetab_offset != -1) { /* * Save this so we can still get the old name. */ const char* fn; fn = source_get(msc_dbg->module, coff_files.files[curr_file_idx].compiland->source); TRACE("Duplicating sect from %s: %x %x %x %d %d\n", fn, aux->Section.Length, aux->Section.NumberOfRelocations, aux->Section.NumberOfLinenumbers, aux->Section.Number, aux->Section.Selection); TRACE("More sect %d %s %08x %d %d %d\n", coff_sym->SectionNumber, coff_get_name(coff_sym, coff_strtab), coff_sym->Value, coff_sym->Type, coff_sym->StorageClass, coff_sym->NumberOfAuxSymbols); /* * Duplicate the file entry. We have no way to describe * multiple text sections in our current way of handling things. */ coff_add_file(&coff_files, msc_dbg->module, fn); } else { TRACE("New text sect from %s: %x %x %x %d %d\n", source_get(msc_dbg->module, coff_files.files[curr_file_idx].compiland->source), aux->Section.Length, aux->Section.NumberOfRelocations, aux->Section.NumberOfLinenumbers, aux->Section.Number, aux->Section.Selection); } if (coff_files.files[curr_file_idx].startaddr > coff_sym->Value) { coff_files.files[curr_file_idx].startaddr = coff_sym->Value; } if (coff_files.files[curr_file_idx].endaddr < coff_sym->Value + aux->Section.Length) { coff_files.files[curr_file_idx].endaddr = coff_sym->Value + aux->Section.Length; } coff_files.files[curr_file_idx].linetab_offset = linetab_indx; coff_files.files[curr_file_idx].linecnt = aux->Section.NumberOfLinenumbers; linetab_indx += aux->Section.NumberOfLinenumbers; i += naux; continue; } if (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC && naux == 0 && coff_sym->SectionNumber == 1) { DWORD base = msc_dbg->sectp[coff_sym->SectionNumber - 1].VirtualAddress; /* * This is a normal static function when naux == 0. * Just register it. The current file is the correct * one in this instance. */ nampnt = coff_get_name(coff_sym, coff_strtab); TRACE("\tAdding static symbol %s\n", nampnt); /* FIXME: was adding symbol to this_file ??? */ coff_add_symbol(&coff_files.files[curr_file_idx], &symt_new_function(msc_dbg->module, coff_files.files[curr_file_idx].compiland, nampnt, msc_dbg->module->module.BaseOfImage + base + coff_sym->Value, 0 /* FIXME */, NULL /* FIXME */)->symt); i += naux; continue; } if (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL && ISFCN(coff_sym->Type) && coff_sym->SectionNumber > 0) { struct symt_compiland* compiland = NULL; DWORD base = msc_dbg->sectp[coff_sym->SectionNumber - 1].VirtualAddress; nampnt = coff_get_name(coff_sym, coff_strtab); TRACE("%d: %s %s\n", i, wine_dbgstr_longlong(msc_dbg->module->module.BaseOfImage + base + coff_sym->Value), nampnt); TRACE("\tAdding global symbol %s (sect=%s)\n", nampnt, msc_dbg->sectp[coff_sym->SectionNumber - 1].Name); /* * Now we need to figure out which file this guy belongs to. */ for (j = 0; j < coff_files.nfiles; j++) { if (coff_files.files[j].startaddr <= base + coff_sym->Value && coff_files.files[j].endaddr > base + coff_sym->Value) { compiland = coff_files.files[j].compiland; break; } } if (j < coff_files.nfiles) { coff_add_symbol(&coff_files.files[j], &symt_new_function(msc_dbg->module, compiland, nampnt, msc_dbg->module->module.BaseOfImage + base + coff_sym->Value, 0 /* FIXME */, NULL /* FIXME */)->symt); } else { symt_new_function(msc_dbg->module, NULL, nampnt, msc_dbg->module->module.BaseOfImage + base + coff_sym->Value, 0 /* FIXME */, NULL /* FIXME */); } i += naux; continue; } if (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL && coff_sym->SectionNumber > 0) { DWORD base = msc_dbg->sectp[coff_sym->SectionNumber - 1].VirtualAddress; struct location loc; /* * Similar to above, but for the case of data symbols. * These aren't treated as entrypoints. */ nampnt = coff_get_name(coff_sym, coff_strtab); TRACE("%d: %s %s\n", i, wine_dbgstr_longlong(msc_dbg->module->module.BaseOfImage + base + coff_sym->Value), nampnt); TRACE("\tAdding global data symbol %s\n", nampnt); /* * Now we need to figure out which file this guy belongs to. */ loc.kind = loc_absolute; loc.reg = 0; loc.offset = msc_dbg->module->module.BaseOfImage + base + coff_sym->Value; symt_new_global_variable(msc_dbg->module, NULL, nampnt, TRUE /* FIXME */, loc, 0 /* FIXME */, NULL /* FIXME */); i += naux; continue; } if (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC && naux == 0) { /* * Ignore these. They don't have anything to do with * reality. */ i += naux; continue; } TRACE("Skipping unknown entry '%s' %d %d %d\n", coff_get_name(coff_sym, coff_strtab), coff_sym->StorageClass, coff_sym->SectionNumber, naux); /* * For now, skip past the aux entries. */ i += naux; } if (coff_files.files != NULL) { /* * OK, we now should have a list of files, and we should have a list * of entrypoints. We need to sort the entrypoints so that we are * able to tie the line numbers with the given functions within the * file. */ for (j = 0; j < coff_files.nfiles; j++) { if (coff_files.files[j].entries != NULL) { qsort(coff_files.files[j].entries, coff_files.files[j].neps, sizeof(struct symt*), symt_cmp_addr); } } /* * Now pick apart the line number tables, and attach the entries * to the given functions. */ for (j = 0; j < coff_files.nfiles; j++) { l = 0; if (coff_files.files[j].neps != 0) { for (k = 0; k < coff_files.files[j].linecnt; k++) { linepnt = coff_linetab + coff_files.files[j].linetab_offset + k; /* * If we have spilled onto the next entrypoint, then * bump the counter.. */ for (;;) { if (l+1 >= coff_files.files[j].neps) break; symt_get_address(coff_files.files[j].entries[l+1], &addr); if (((msc_dbg->module->module.BaseOfImage + linepnt->Type.VirtualAddress) < addr)) break; l++; } if (coff_files.files[j].entries[l+1]->tag == SymTagFunction) { /* * Add the line number. This is always relative to the * start of the function, so we need to subtract that offset * first. */ symt_get_address(coff_files.files[j].entries[l+1], &addr); symt_add_func_line(msc_dbg->module, (struct symt_function*)coff_files.files[j].entries[l+1], coff_files.files[j].compiland->source, linepnt->Linenumber, msc_dbg->module->module.BaseOfImage + linepnt->Type.VirtualAddress - addr); } } } } for (j = 0; j < coff_files.nfiles; j++) { HeapFree(GetProcessHeap(), 0, coff_files.files[j].entries); } HeapFree(GetProcessHeap(), 0, coff_files.files); msc_dbg->module->module.SymType = SymCoff; /* FIXME: we could have a finer grain here */ msc_dbg->module->module.LineNumbers = TRUE; msc_dbg->module->module.GlobalSymbols = TRUE; msc_dbg->module->module.TypeInfo = FALSE; msc_dbg->module->module.SourceIndexed = TRUE; msc_dbg->module->module.Publics = TRUE; ret = TRUE; } return ret; }
int source_get() { int c; source_last = c = source_peek; switch (c) { case EOF: { fclose(source_file); if (include_depth) { include_depth--; source_file = stack[include_depth].file; source_line = stack[include_depth].line; source_name = stack[include_depth].name; source_peek = getc(source_file); c = source_get(); } } return c; case '\n': source_line++; default: if (c==nw_char) { /* Handle an ``at'' character */ { c = getc(source_file); if (double_at) { source_peek = c; double_at = FALSE; c = nw_char; } else switch (c) { case 'i': { char name[FILENAME_MAX]; char fullname[FILENAME_MAX]; struct incl * p = include_list; if (include_depth >= 10) { fprintf(stderr, "%s: include nesting too deep (%s, %d)\n", command_name, source_name, source_line); exit(-1); } /* Collect include-file name */ { char *p = name; do c = getc(source_file); while (c == ' ' || c == '\t'); while (isgraph(c)) { *p++ = c; c = getc(source_file); } *p = '\0'; if (c != '\n') { fprintf(stderr, "%s: unexpected characters after file name (%s, %d)\n", command_name, source_name, source_line); exit(-1); } } stack[include_depth].file = source_file; fullname[0] = '\0'; for (;;) { strcat(fullname, name); source_file = fopen(fullname, "r"); if (source_file || !p) break; strcpy(fullname, p->name); strcat(fullname, "/"); p = p->next; } if (!source_file) { fprintf(stderr, "%s: can't open include file %s\n", command_name, name); source_file = stack[include_depth].file; } else { stack[include_depth].name = source_name; stack[include_depth].line = source_line + 1; include_depth++; source_line = 1; source_name = save_string(fullname); } source_peek = getc(source_file); c = source_get(); } break; case '#': case 'f': case 'm': case 'u': case 'v': case 'd': case 'o': case 'D': case 'O': case 's': case 'q': case 'Q': case 'S': case 't': case '+': case '-': case '*': case '\'': case '{': case '}': case '<': case '>': case '|': case '(': case ')': case '[': case ']': case '%': case '_': case ':': case ',': case 'x': case 'c': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'r': source_peek = c; c = nw_char; break; default: if (c==nw_char) { source_peek = c; double_at = TRUE; break; } fprintf(stderr, "%s: bad %c sequence %c[%d] (%s, line %d)\n", command_name, nw_char, c, c, source_name, source_line); exit(-1); } } return c; } source_peek = getc(source_file); return c; } }
int conf_group_set(struct ipc_user *u, char *data, size_t len, __unused struct blob_buf *reply) { conf conf = container_of(u, conf_s, ipc_users[CONF_IPC_GROUP_SET]); ifgroups igs = conf->igs; pim pim = conf->pim; struct blob_attr *tb[CONF_G_MAX]; struct in6_addr grp, src; group g = NULL; source s = NULL; gsource gs = NULL; iface i = NULL; ifgroup ig = NULL; ifgsource ifgs = NULL; int join = 0, listen = 0, local = 0; char *str; int ret = 0; if(blobmsg_parse(conf_g_attrs, CONF_G_MAX, tb, data, len) || !tb[CONF_G_GROUP] || !addr_pton(&grp, blobmsg_get_string(tb[CONF_G_GROUP])) || !addr_is_multicast(&grp) || (tb[CONF_G_SRC] && !addr_pton(&src, blobmsg_get_string(tb[CONF_G_SRC]))) || (tb[CONF_G_LISTENER] && !tb[CONF_G_DEV])) return -EINVAL; if(tb[CONF_G_PIM]) { if(!(str = blobmsg_get_string(tb[CONF_G_PIM]))) return -EINVAL; else if (!strcmp(str, "join")) join = PIM_JOIN; else if(!strcmp(str, "prune")) join = PIM_PRUNE; else if(!strcmp(str, "none")) join = PIM_NONE; else return -EINVAL; } if(tb[CONF_G_LISTENER]) { if(!(str = blobmsg_get_string(tb[CONF_G_LISTENER]))) return -EINVAL; else if (!strcmp(str, "include")) listen = PIM_JOIN; else if(!strcmp(str, "exclude")) listen = PIM_PRUNE; else if(!strcmp(str, "none")) listen = PIM_NONE; else return -EINVAL; } if(tb[CONF_G_LOCAL]) { if(!(str = blobmsg_get_string(tb[CONF_G_LOCAL]))) return -EINVAL; else if (!strcmp(str, "include")) local = PIM_JOIN; else if(!strcmp(str, "exclude")) local = PIM_PRUNE; else if(!strcmp(str, "none")) local = PIM_NONE; else return -EINVAL; } if((tb[CONF_G_LOCAL] && !tb[CONF_G_DEV]) || (tb[CONF_G_LISTENER] && !tb[CONF_G_DEV])) return -EINVAL; if((tb[CONF_G_GROUP] && (!(g = group_get(igs, &grp, 1)) || !group_ref(g))) || (tb[CONF_G_SRC] && ((!(s = source_get(igs, &src, 1)) || !group_ref(s)) || (!(gs = gsource_get(g, s, 1)) || !gsource_ref(gs)))) || (tb[CONF_G_DEV] && ((!(i = iface_get_byname(igs, blobmsg_get_string(tb[CONF_G_DEV]), 1)) || !iface_ref(i)) || (!(ig = ifgroup_get(i, g, 1)) || !ifgroup_ref(ig)))) || (ig && gs && (!(ifgs = ifgsource_get(ig, gs, 1)) || !ifgsource_ref(ifgs)))) { ret = -ENOMEM; goto out; } if(tb[CONF_G_PIM]) { if(gs) { L_INFO("Set configuration of gsource "GSOURCE_L" - pim_join_desired : %s", GSOURCE_LA(gs), PIM_STATE_STR(join)); if(!gs->conf_join_desired) gsource_ref(gs); gs->conf_join_desired = join; pim_gsource_conf_changed(pim, gs); if(!gs->conf_join_desired) gsource_unref(gs); } else { L_INFO("Set configuration of group "GROUP_L" - pim_join_desired : %s", GROUP_LA(g), PIM_STATE_STR(join)); if(!g->conf_join_desired) group_ref(g); g->conf_join_desired = join; pim_group_conf_changed(pim, g); if(!g->conf_join_desired) group_unref(g); } } if(tb[CONF_G_LOCAL]) { L_INFO("Set configuration of ifgroup "IFGROUP_L" - local_exclude : %d", IFGROUP_LA(ig), (local == PIM_PRUNE)); if(!ig->conf_local_exclude) ifgroup_ref(ig); ig->conf_local_exclude = !!(local == PIM_PRUNE); pim_ifgroup_conf_changed(pim, ig); if(!ig->conf_local_exclude) ifgroup_unref(ig); } if (tb[CONF_G_LISTENER]) { if(ifgs) { listener_update_G_S(ifgs, LISTENER_CONF, listen == PIM_JOIN, listen == PIM_PRUNE); } else { listener_update_G(ig, LISTENER_CONF, listen == PIM_PRUNE); } } out: if(ifgs) ifgsource_unref(ifgs); if(gs) gsource_unref(gs); if(ig) ifgroup_unref(ig); if(g) group_unref(g); if(s) source_unref(s); if(i) iface_unref(i); return ret; }