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

📄 elf_module.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
                do
                {
                    if (!ReadProcessMemory(pcs->handle, ptr, &dyn, sizeof(dyn), &len) ||
                        len != sizeof(dyn) || !is_dt_flag_valid(dyn.d_tag))
                        dyn.d_tag = DT_NULL;
                    ptr += sizeof(dyn);
                } while (dyn.d_tag != DT_DEBUG && dyn.d_tag != DT_NULL);
                if (dyn.d_tag == DT_NULL) goto leave;
                elf_info->dbg_hdr_addr = dyn.d_un.d_ptr;
            }
	}
    }

    if (elf_info->flags & ELF_INFO_MODULE)
    {
        struct elf_module_info *elf_module_info = 
            HeapAlloc(GetProcessHeap(), 0, sizeof(struct elf_module_info));
        if (!elf_module_info) goto leave;
        elf_info->module = module_new(pcs, filename, DMT_ELF, 
                                        (load_offset) ? load_offset : start, 
                                        size, 0, 0);
        if (!elf_info->module)
        {
            HeapFree(GetProcessHeap(), 0, elf_module_info);
            goto leave;
        }
        elf_info->module->elf_info = elf_module_info;
        elf_info->module->elf_info->elf_addr = load_offset;

        if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
        {
            elf_info->module->module.SymType = SymDeferred;
            ret = TRUE;
        }
        else ret = elf_load_debug_info(elf_info->module);

        elf_info->module->elf_info->elf_mark = 1;
        elf_info->module->elf_info->elf_loader = 0;
    } else ret = TRUE;

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

    return ret;
}

/******************************************************************
 *		elf_load_file_from_path
 * tries to load an ELF file from a set of paths (separated by ':')
 */
static BOOL elf_load_file_from_path(HANDLE hProcess,
                                    const char* filename,
                                    unsigned long load_offset,
                                    const char* path,
                                    struct elf_info* elf_info)
{
    BOOL                ret = FALSE;
    char                *s, *t, *fn;
    char*	        paths = NULL;

    if (!path) return FALSE;

    paths = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(path) + 1), path);
    for (s = paths; s && *s; s = (t) ? (t+1) : NULL) 
    {
	t = strchr(s, ':');
	if (t) *t = '\0';
	fn = HeapAlloc(GetProcessHeap(), 0, strlen(filename) + 1 + strlen(s) + 1);
	if (!fn) break;
	strcpy(fn, s);
	strcat(fn, "/");
	strcat(fn, filename);
	ret = elf_load_file(hProcess, fn, load_offset, elf_info);
	HeapFree(GetProcessHeap(), 0, fn);
	if (ret) break;
	s = (t) ? (t+1) : NULL;
    }
    
    HeapFree(GetProcessHeap(), 0, paths);
    return ret;
}

/******************************************************************
 *		elf_search_and_load_file
 *
 * lookup a file in standard ELF locations, and if found, load it
 */
static BOOL elf_search_and_load_file(struct process* pcs, const char* filename,
                                     unsigned long load_offset, 
                                     struct elf_info* elf_info)
{
    BOOL                ret = FALSE;
    struct module*      module;

    if (filename == NULL || *filename == '\0') return FALSE;
    if ((module = module_find_by_name(pcs, filename, DMT_ELF)))
    {
        elf_info->module = module;
        module->elf_info->elf_mark = 1;
        return module->module.SymType;
    }

    if (strstr(filename, "libstdc++")) return FALSE; /* We know we can't do it */
    ret = elf_load_file(pcs, filename, load_offset, elf_info);
    /* if relative pathname, try some absolute base dirs */
    if (!ret && !strchr(filename, '/'))
    {
        ret = elf_load_file_from_path(pcs, filename, load_offset, 
                                      getenv("PATH"), elf_info) ||
            elf_load_file_from_path(pcs, filename, load_offset,
                                    getenv("LD_LIBRARY_PATH"), elf_info) ||
            elf_load_file_from_path(pcs, filename, load_offset,
                                    getenv("WINEDLLPATH"), elf_info);
    }
    
    return ret;
}

/******************************************************************
 *		elf_synchronize_module_list
 *
 * this functions rescans the debuggee module's list and synchronizes it with
 * the one from 'pcs', ie:
 * - if a module is in debuggee and not in pcs, it's loaded into pcs
 * - if a module is in pcs and not in debuggee, it's unloaded from pcs
 */
BOOL	elf_synchronize_module_list(struct process* pcs)
{
    struct r_debug      dbg_hdr;
    void*               lm_addr;
    struct link_map     lm;
    char		bufstr[256];
    struct elf_info     elf_info;
    struct module*      module;

    if (!pcs->dbg_hdr_addr ||
        !ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr, 
                           &dbg_hdr, sizeof(dbg_hdr), NULL))
        return FALSE;

    for (module = pcs->lmodules; module; module = module->next)
    {
        if (module->type == DMT_ELF) module->elf_info->elf_mark = 0;
    }

    elf_info.flags = ELF_INFO_MODULE;
    /* Now walk the linked list.  In all known ELF implementations,
     * the dynamic loader maintains this linked list for us.  In some
     * cases the first entry doesn't appear with a name, in other cases it
     * does.
     */
    for (lm_addr = (void*)dbg_hdr.r_map; lm_addr; lm_addr = (void*)lm.l_next)
    {
	if (!ReadProcessMemory(pcs->handle, lm_addr, &lm, sizeof(lm), NULL))
	    return FALSE;

	if (lm.l_prev != NULL && /* skip first entry, normally debuggee itself */
	    lm.l_name != NULL &&
	    ReadProcessMemory(pcs->handle, lm.l_name, bufstr, sizeof(bufstr), NULL)) 
        {
	    bufstr[sizeof(bufstr) - 1] = '\0';
            elf_search_and_load_file(pcs, bufstr, (unsigned long)lm.l_addr,
                                     &elf_info);
	}
    }

    for (module = pcs->lmodules; module; module = module->next)
    {
        if (module->type == DMT_ELF && !module->elf_info->elf_mark && 
            !module->elf_info->elf_loader)
        {
            module_remove(pcs, module);
            /* restart all over */
            module = pcs->lmodules;
        }
    }
    return TRUE;
}

/******************************************************************
 *		elf_read_wine_loader_dbg_info
 *
 * Try to find a decent wine executable which could have loaded the debuggee
 */
BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
{
    const char*         ptr;
    struct elf_info     elf_info;
    BOOL                ret;

    elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE;
    /* All binaries are loaded with WINELOADER (if run from tree) or by the
     * main executable (either wine-kthread or wine-pthread)
     * Note: the heuristic use to know whether we need to load wine-pthread or
     * wine-kthread is not 100% safe
     */
    if ((ptr = getenv("WINELOADER")))
        ret = elf_search_and_load_file(pcs, ptr, 0, &elf_info);
    else 
    {
        ret = elf_search_and_load_file(pcs, "wine-kthread", 0, &elf_info) ||
            elf_search_and_load_file(pcs, "wine-pthread", 0, &elf_info);
    }
    if (!ret) return FALSE;
    elf_info.module->elf_info->elf_loader = 1;
    strcpy(elf_info.module->module.ModuleName, "<wine-loader>");
    return (pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr) != 0;
}

/******************************************************************
 *		elf_load_module
 *
 * loads an ELF module and stores it in process' module list
 * Also, find module real name and load address from
 * the real loaded modules list in pcs address space
 */
struct module*  elf_load_module(struct process* pcs, const char* name)
{
    struct elf_info     elf_info;
    BOOL                ret = FALSE;
    const char*         p;
    const char*         xname;
    struct r_debug      dbg_hdr;
    void*               lm_addr;
    struct link_map     lm;
    char                bufstr[256];

    TRACE("(%p %s)\n", pcs, name);

    elf_info.flags = ELF_INFO_MODULE;

    /* do only the lookup from the filename, not the path (as we lookup module name
     * in the process' loaded module list)
     */
    xname = strrchr(name, '/');
    if (!xname++) xname = name;

    if (!ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr, &dbg_hdr, sizeof(dbg_hdr), NULL))
        return NULL;

    for (lm_addr = (void*)dbg_hdr.r_map; lm_addr; lm_addr = (void*)lm.l_next)
    {
        if (!ReadProcessMemory(pcs->handle, lm_addr, &lm, sizeof(lm), NULL))
            return NULL;

        if (lm.l_prev != NULL && /* skip first entry, normally debuggee itself */
            lm.l_name != NULL &&
            ReadProcessMemory(pcs->handle, lm.l_name, bufstr, sizeof(bufstr), NULL)) 
        {
            bufstr[sizeof(bufstr) - 1] = '\0';
            /* memcmp is needed for matches when bufstr contains also version information
             * name: libc.so, bufstr: libc.so.6.0
             */
            p = strrchr(bufstr, '/');
            if (!p++) p = bufstr;
            if (!memcmp(p, xname, strlen(xname)))
            {
                ret = elf_search_and_load_file(pcs, bufstr,
                                               (unsigned long)lm.l_addr, &elf_info);
                break;
            }
        }
    }
    if (!lm_addr || !ret) return NULL;
    assert(elf_info.module);
    return elf_info.module;
}

#else	/* !__ELF__ */

BOOL	elf_synchronize_module_list(struct process* pcs)
{
    return FALSE;
}

BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
{
    return FALSE;
}

struct module*  elf_load_module(struct process* pcs, const char* name)
{
    return NULL;
}

BOOL elf_load_debug_info(struct module* module)
{
    return FALSE;
}
#endif  /* __ELF__ */

⌨️ 快捷键说明

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