⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 elf_module.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
 * Loads the symbolic information from ELF module stored in 'file'
 * the module has been loaded at 'load_offset' address, so symbols' address
 * relocation is performed. crc optionally points to the CRC of the debug file
 * to load.
 * returns
 *	0 if the file doesn't contain symbolic info (or this info cannot be
 *	read or parsed)
 *	1 on success
 */
static BOOL elf_load_debug_info_from_file(
    struct module* module, const char* file, struct pool* pool,
    struct hash_table* ht_symtab, const DWORD *crc)
{
    BOOL                ret = FALSE;
    char*	        addr = (char*)0xffffffff;
    int		        fd = -1;
    struct stat	        statbuf;
    const Elf32_Ehdr*   ehptr;
    const Elf32_Shdr*   spnt;
    const char*	        shstrtab;
    int	       	        i;
    int                 symtab_sect, dynsym_sect, stab_sect, stabstr_sect, debug_sect, debuglink_sect;
    struct thunk_area   thunks[] = 
    {
        {"__wine_spec_import_thunks",           THUNK_ORDINAL_NOTYPE, 0, 0},    /* inter DLL calls */
        {"__wine_spec_delayed_import_loaders",  THUNK_ORDINAL_LOAD,   0, 0},    /* delayed inter DLL calls */
        {"__wine_spec_delayed_import_thunks",   THUNK_ORDINAL_LOAD,   0, 0},    /* delayed inter DLL calls */
        {"__wine_delay_load",                   THUNK_ORDINAL_LOAD,   0, 0},    /* delayed inter DLL calls */
        {"__wine_spec_thunk_text_16",           -16,                  0, 0},    /* 16 => 32 thunks */
        {"__wine_spec_thunk_data_16",           -16,                  0, 0},    /* 16 => 32 thunks */
        {"__wine_spec_thunk_text_32",           -32,                  0, 0},    /* 32 => 16 thunks */
        {"__wine_spec_thunk_data_32",           -32,                  0, 0},    /* 32 => 16 thunks */
    };

    if (module->type != DMT_ELF || !module->elf_info)
    {
	ERR("Bad elf module '%s'\n", module->module.LoadedImageName);
	return FALSE;
    }

    TRACE("%s\n", file);
    /* check that the file exists, and that the module hasn't been loaded yet */
    if (stat(file, &statbuf) == -1) goto leave;
    if (S_ISDIR(statbuf.st_mode)) goto leave;

    /*
     * Now open the file, so that we can mmap() it.
     */
    if ((fd = open(file, O_RDONLY)) == -1) goto leave;

    /*
     * Now mmap() the file.
     */
    addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (addr == (char*)0xffffffff) goto leave;

    if (crc && (*crc != calc_crc32(addr, statbuf.st_size)))
    {
        ERR("Bad CRC for file %s\n", file);
        /* we don't tolerate mis-matched files */
        goto leave;
    }

    /*
     * Next, we need to find a few of the internal ELF headers within
     * this thing.  We need the main executable header, and the section
     * table.
     */
    ehptr = (Elf32_Ehdr*)addr;
    spnt = (Elf32_Shdr*)(addr + ehptr->e_shoff);
    shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);

    symtab_sect = dynsym_sect = stab_sect = stabstr_sect = debug_sect = debuglink_sect = -1;

    for (i = 0; i < ehptr->e_shnum; i++)
    {
	if (strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0)
	    stab_sect = i;
	if (strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0)
	    stabstr_sect = i;
	if (strcmp(shstrtab + spnt[i].sh_name, ".debug_info") == 0)
	    debug_sect = i;
	if (strcmp(shstrtab + spnt[i].sh_name, ".gnu_debuglink") == 0)
	    debuglink_sect = i;
	if ((strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0) &&
	    (spnt[i].sh_type == SHT_SYMTAB))
            symtab_sect = i;
        if ((strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0) &&
            (spnt[i].sh_type == SHT_DYNSYM))
            dynsym_sect = i;
    }

    if (symtab_sect == -1)
    {
        /* if we don't have a symtab but a dynsym, process the dynsym
         * section instead. It'll contain less (relevant) information, 
         * but it'll be better than nothing
         */
        if (dynsym_sect == -1) goto leave;
        symtab_sect = dynsym_sect;
    }

    module->module.SymType = SymExport;

    /* create a hash table for the symtab */
    elf_hash_symtab(module, pool, ht_symtab, addr, 
                    spnt + symtab_sect, spnt + spnt[symtab_sect].sh_link,
                    sizeof(thunks) / sizeof(thunks[0]), thunks);

    if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
    {
        if (stab_sect != -1 && stabstr_sect != -1)
        {
            /* OK, now just parse all of the stabs. */
            ret = stabs_parse(module, module->elf_info->elf_addr,
                              addr + spnt[stab_sect].sh_offset,
                              spnt[stab_sect].sh_size,
                              addr + spnt[stabstr_sect].sh_offset,
                              spnt[stabstr_sect].sh_size);
            if (!ret)
            {
                WARN("Couldn't read correctly read stabs\n");
                goto leave;
            }
            /* and fill in the missing information for stabs */
            elf_finish_stabs_info(module, ht_symtab);
        }
        else if (debug_sect != -1)
        {
            /* Dwarf 2 debug information */
            FIXME("Unsupported Dwarf2 information for %s\n", module->module.ModuleName);
        }
        else if (debuglink_sect != -1)
        {
            DWORD crc;
            const char * file = (const char *)(addr + spnt[debuglink_sect].sh_offset);
            /* crc is stored after the null terminated file string rounded
             * up to the next 4 byte boundary */
            crc = *(const DWORD *)(file + ((DWORD_PTR)(strlen(file) + 4) & ~3));
            ret = elf_load_debug_info_from_file(module, file, pool, ht_symtab, &crc);
            if (!ret)
                WARN("Couldn't load linked debug file %s\n", file);
        }
    }
    if (strstr(module->module.ModuleName, "<elf>") ||
        !strcmp(module->module.ModuleName, "<wine-loader>"))
    {
        /* add the thunks for native libraries */
        if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
            elf_new_wine_thunks(module, ht_symtab, 
                                sizeof(thunks) / sizeof(thunks[0]), thunks);
    }
    /* add all the public symbols from symtab */
    if (elf_new_public_symbols(module, ht_symtab) && !ret) ret = TRUE;

leave:
    if (addr != (char*)0xffffffff) munmap(addr, statbuf.st_size);
    if (fd != -1) close(fd);

    return ret;
}

/******************************************************************
 *		elf_load_debug_info
 *
 * Loads ELF debugging information from the module image file.
 */
BOOL elf_load_debug_info(struct module* module)
{
    BOOL              ret;
    struct pool       pool;
    struct hash_table ht_symtab;

    pool_init(&pool, 65536);
    hash_table_init(&pool, &ht_symtab, 256);

    ret = elf_load_debug_info_from_file(module,
        module->module.LoadedImageName, &pool, &ht_symtab, NULL);

    pool_destroy(&pool);

    return ret;
}


/******************************************************************
 *		is_dt_flag_valid
 * returns true iff the section tag is valid 
 */
static unsigned is_dt_flag_valid(unsigned d_tag)
{
#ifndef DT_PROCNUM
#define DT_PROCNUM 0
#endif
#ifndef DT_EXTRANUM
#define DT_EXTRANUM 0
#endif
    return (d_tag >= 0 && d_tag < DT_NUM + DT_PROCNUM + DT_EXTRANUM)
#if defined(DT_LOOS) && defined(DT_HIOS)
        || (d_tag >= DT_LOOS && d_tag < DT_HIOS)
#endif
#if defined(DT_LOPROC) && defined(DT_HIPROC)
        || (d_tag >= DT_LOPROC && d_tag < DT_HIPROC)
#endif
        ;
}

/******************************************************************
 *		elf_load_file
 *
 * Loads the information for ELF module stored in 'filename'
 * the module has been loaded at 'load_offset' address
 * returns
 *	-1 if the file cannot be found/opened
 *	0 if the file doesn't contain symbolic info (or this info cannot be
 *	read or parsed)
 *	1 on success
 */
static BOOL elf_load_file(struct process* pcs, const char* filename,
                          unsigned long load_offset, struct elf_info* elf_info)
{
    static const BYTE   elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 };
    BOOL                ret = FALSE;
    const char*	        addr = (char*)0xffffffff;
    int		        fd = -1;
    struct stat	        statbuf;
    const Elf32_Ehdr*   ehptr;
    const Elf32_Shdr*   spnt;
    const Elf32_Phdr*	ppnt;
    const char*         shstrtab;
    int	       	        i;
    DWORD	        size, start;
    unsigned            tmp, page_mask = getpagesize() - 1;

    TRACE("Processing elf file '%s' at %08lx\n", filename, load_offset);

    /* check that the file exists, and that the module hasn't been loaded yet */
    if (stat(filename, &statbuf) == -1) goto leave;

    /* Now open the file, so that we can mmap() it. */
    if ((fd = open(filename, O_RDONLY)) == -1) goto leave;

    /* Now mmap() the file. */
    addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (addr == (char*)-1) goto leave;

    /* Next, we need to find a few of the internal ELF headers within
     * this thing.  We need the main executable header, and the section
     * table.
     */
    ehptr = (const Elf32_Ehdr*)addr;
    if (memcmp(ehptr->e_ident, elf_signature, sizeof(elf_signature))) goto leave;

    spnt = (const Elf32_Shdr*)(addr + ehptr->e_shoff);
    shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);

    /* grab size of module once loaded in memory */
    ppnt = (const Elf32_Phdr*)(addr + ehptr->e_phoff);
    size = 0; start = ~0L;

    for (i = 0; i < ehptr->e_phnum; i++)
    {
        if (ppnt[i].p_type == PT_LOAD)
        {
            tmp = (ppnt[i].p_vaddr + ppnt[i].p_memsz + page_mask) & ~page_mask;
            if (size < tmp) size = tmp;
            if (ppnt[i].p_vaddr < start) start = ppnt[i].p_vaddr;
        }
    }

    /* if non relocatable ELF, then remove fixed address from computation
     * otherwise, all addresses are zero based and start has no effect
     */
    size -= start;
    if (!start && !load_offset)
        ERR("Relocatable ELF %s, but no load address. Loading at 0x0000000\n",
            filename);
    if (start && load_offset)
    {
        WARN("Non-relocatable ELF %s, but load address of 0x%08lx supplied. "
             "Assuming load address is corrupt\n", filename, load_offset);
        load_offset = 0;
    }

    if (elf_info->flags & ELF_INFO_DEBUG_HEADER)
    {
        for (i = 0; i < ehptr->e_shnum; i++)
        {
            if (strcmp(shstrtab + spnt[i].sh_name, ".dynamic") == 0 &&
                spnt[i].sh_type == SHT_DYNAMIC)
            {
                Elf32_Dyn       dyn;
                char*           ptr = (char*)spnt[i].sh_addr;
                unsigned long   len;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -