Beispiel #1
0
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;
}
Beispiel #2
0
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;
  }
}
Beispiel #3
0
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;
}