Beispiel #1
0
/******************************************************************
 *		pe_locate_with_coff_symbol_table
 *
 * Use the COFF symbol table (if any) from the IMAGE_FILE_HEADER to set the absolute address
 * of global symbols.
 * Mingw32 requires this for stabs debug information as address for global variables isn't filled in
 * (this is similar to what is done in elf_module.c when using the .symtab ELF section)
 */
static BOOL pe_locate_with_coff_symbol_table(struct module* module)
{
    struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap;
    const IMAGE_SYMBOL* isym;
    int                 i, numsym, naux;
    char                tmp[9];
    const char*         name;
    struct hash_table_iter      hti;
    void*               ptr;
    struct symt_data*   sym;
    const char*         mapping;

    numsym = fmap->u.pe.ntheader.FileHeader.NumberOfSymbols;
    if (!fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable || !numsym)
        return TRUE;
    if (!(mapping = pe_map_full(fmap, NULL))) return FALSE;
    isym = (const IMAGE_SYMBOL*)(mapping + fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable);

    for (i = 0; i < numsym; i+= naux, isym += naux)
    {
        if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
            isym->SectionNumber > 0 && isym->SectionNumber <= fmap->u.pe.ntheader.FileHeader.NumberOfSections)
        {
            if (isym->N.Name.Short)
            {
                name = memcpy(tmp, isym->N.ShortName, 8);
                tmp[8] = '\0';
            }
            else name = fmap->u.pe.strtable + isym->N.Name.Long;
            if (name[0] == '_') name++;
            hash_table_iter_init(&module->ht_symbols, &hti, name);
            while ((ptr = hash_table_iter_up(&hti)))
            {
                sym = CONTAINING_RECORD(ptr, struct symt_data, hash_elt);
                if (sym->symt.tag == SymTagData &&
                    (sym->kind == DataIsGlobal || sym->kind == DataIsFileStatic) &&
                    sym->u.var.kind == loc_absolute &&
                    !strcmp(sym->hash_elt.name, name))
                {
                    TRACE("Changing absolute address for %d.%s: %lx -> %s\n",
                          isym->SectionNumber, name, sym->u.var.offset,
                          wine_dbgstr_longlong(module->module.BaseOfImage +
                                               fmap->u.pe.sect[isym->SectionNumber - 1].shdr.VirtualAddress +
                                               isym->Value));
                    sym->u.var.offset = module->module.BaseOfImage +
                        fmap->u.pe.sect[isym->SectionNumber - 1].shdr.VirtualAddress + isym->Value;
                    break;
                }
            }
        }
        naux = isym->NumberOfAuxSymbols + 1;
    }
    pe_unmap_full(fmap);
    return TRUE;
}
Beispiel #2
0
int module_compute_num_syms(struct module* module)
{
    struct hash_table_iter      hti;
    void*                       ptr;

    module->module.NumSyms = 0;
    hash_table_iter_init(&module->ht_symbols, &hti, NULL);
    while ((ptr = hash_table_iter_up(&hti)))
         module->module.NumSyms++;
    return module->module.NumSyms;
}
Beispiel #3
0
/******************************************************************
 *              macho_finish_stabs
 *
 * Integrate the non-debugging symbols we've gathered into the
 * symbols that were generated during stabs parsing.
 */
static void macho_finish_stabs(struct module* module, struct hash_table* ht_symtab)
{
    struct hash_table_iter      hti_ours;
    struct symtab_elt*          ste;
    BOOL                        adjusted = FALSE;

    TRACE("(%p, %p)\n", module, ht_symtab);

    /* For each of our non-debugging symbols, see if it can provide some
     * missing details to one of the module's known symbols. */
    hash_table_iter_init(ht_symtab, &hti_ours, NULL);
    while ((ste = hash_table_iter_up(&hti_ours)))
    {
        struct hash_table_iter  hti_modules;
        void*                   ptr;
        struct symt_ht*         sym;
        struct symt_function*   func;
        struct symt_data*       data;

        hash_table_iter_init(&module->ht_symbols, &hti_modules, ste->ht_elt.name);
        while ((ptr = hash_table_iter_up(&hti_modules)))
        {
            sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);

            if (strcmp(sym->hash_elt.name, ste->ht_elt.name))
                continue;

            switch (sym->symt.tag)
            {
            case SymTagFunction:
                func = (struct symt_function*)sym;
                if (func->address == module->format_info[DFI_MACHO]->u.macho_info->load_addr)
                {
                    TRACE("Adjusting function %p/%s!%s from 0x%08lx to 0x%08lx\n", func,
                          debugstr_w(module->module.ModuleName), sym->hash_elt.name,
                          func->address, ste->addr);
                    func->address = ste->addr;
                    adjusted = TRUE;
                }
                if (func->address == ste->addr)
                    ste->used = 1;
                break;
            case SymTagData:
                data = (struct symt_data*)sym;
                switch (data->kind)
                {
                case DataIsGlobal:
                case DataIsFileStatic:
                    if (data->u.var.offset == module->format_info[DFI_MACHO]->u.macho_info->load_addr)
                    {
                        TRACE("Adjusting data symbol %p/%s!%s from 0x%08lx to 0x%08lx\n",
                              data, debugstr_w(module->module.ModuleName), sym->hash_elt.name,
                              data->u.var.offset, ste->addr);
                        data->u.var.offset = ste->addr;
                        adjusted = TRUE;
                    }
                    if (data->u.var.offset == ste->addr)
                    {
                        enum DataKind new_kind;

                        new_kind = ste->is_global ? DataIsGlobal : DataIsFileStatic;
                        if (data->kind != new_kind)
                        {
                            WARN("Changing kind for %p/%s!%s from %d to %d\n", sym,
                                 debugstr_w(module->module.ModuleName), sym->hash_elt.name,
                                 (int)data->kind, (int)new_kind);
                            data->kind = new_kind;
                            adjusted = TRUE;
                        }
                        ste->used = 1;
                    }
                    break;
                default:;
                }
                break;
            default:
                TRACE("Ignoring tag %u\n", sym->symt.tag);
                break;
            }
        }
    }

    if (adjusted)
    {
        /* since we may have changed some addresses, mark the module to be resorted */
        module->sortlist_valid = FALSE;
    }

    /* Mark any of our non-debugging symbols which fall on an already-used
     * address as "used".  This allows us to skip them in the next loop,
     * below.  We do this in separate loops because symt_new_* marks the
     * list as needing sorting and symt_find_nearest sorts if needed,
     * causing thrashing. */
    if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
    {
        hash_table_iter_init(ht_symtab, &hti_ours, NULL);
        while ((ste = hash_table_iter_up(&hti_ours)))
        {
            struct symt_ht* sym;
            ULONG64         addr;

            if (ste->used) continue;

            sym = symt_find_nearest(module, ste->addr);
            if (sym)
                symt_get_address(&sym->symt, &addr);
            if (sym && ste->addr == addr)
            {
                ULONG64 size = 0;
                DWORD   kind = -1;

                ste->used = 1;

                /* If neither symbol has a correct size (ours never does), we
                 * consider them both to be markers.  No warning is needed in
                 * that case.
                 * Also, we check that we don't have two symbols, one local, the other
                 * global, which is legal.
                 */
                symt_get_info(module, &sym->symt, TI_GET_LENGTH,   &size);
                symt_get_info(module, &sym->symt, TI_GET_DATAKIND, &kind);
                if (size && kind == (ste->is_global ? DataIsGlobal : DataIsFileStatic))
                    FIXME("Duplicate in %s: %s<%08lx> %s<%s-%s>\n",
                          debugstr_w(module->module.ModuleName),
                          ste->ht_elt.name, ste->addr,
                          sym->hash_elt.name,
                          wine_dbgstr_longlong(addr), wine_dbgstr_longlong(size));
            }
        }
    }

    /* For any of our remaining non-debugging symbols which have no match
     * among the module's known symbols, add them as new symbols. */
    hash_table_iter_init(ht_symtab, &hti_ours, NULL);
    while ((ste = hash_table_iter_up(&hti_ours)))
    {
        if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY) && !ste->used)
        {
            if (ste->is_code)
            {
                symt_new_function(module, ste->compiland, ste->ht_elt.name,
                    ste->addr, 0, NULL);
            }
            else
            {
                struct location loc;

                loc.kind = loc_absolute;
                loc.reg = 0;
                loc.offset = ste->addr;
                symt_new_global_variable(module, ste->compiland, ste->ht_elt.name,
                                         !ste->is_global, loc, 0, NULL);
            }

            ste->used = 1;
        }

        if (ste->is_public && !(dbghelp_options & SYMOPT_NO_PUBLICS))
        {
            symt_new_public(module, ste->compiland, ste->ht_elt.name, ste->addr, 0);
        }
    }
}