From 99e818154a803c8cfd2478b9db3b455fc9adef30 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 4 Jun 2018 16:51:34 -0500 Subject: [PATCH] dbghelp: Read the r_debug and link_map structs corresponding to the target's architecture. Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/dbghelp/elf_module.c | 110 +++++++++++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 26 deletions(-) diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index c43d10812c3..32ce3455db0 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -78,6 +78,15 @@ struct r_debug }; #endif /* HAVE_STRUCT_R_DEBUG */ +struct r_debug32 +{ + int r_version; + DWORD r_map; + Elf32_Addr r_brk; + int r_state; + Elf32_Addr r_ldbase; +}; + #ifndef HAVE_STRUCT_LINK_MAP struct link_map { @@ -88,6 +97,14 @@ struct link_map }; #endif /* HAVE_STRUCT_LINK_MAP */ +struct link_map32 +{ + Elf32_Addr l_addr; + DWORD l_name; + DWORD l_ld; + DWORD l_next, l_prev; +}; + WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); struct elf_info @@ -1648,36 +1665,77 @@ static BOOL elf_enum_modules_internal(const struct process* pcs, const WCHAR* main_name, enum_elf_modules_cb cb, void* user) { - struct r_debug dbg_hdr; - void* lm_addr; - struct link_map lm; - char bufstr[256]; - WCHAR bufstrW[MAX_PATH]; + WCHAR bufstrW[MAX_PATH]; + char bufstr[256]; + void *lm_addr; - if (!pcs->dbg_hdr_addr || - !ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr, - &dbg_hdr, sizeof(dbg_hdr), NULL)) - return FALSE; - - /* 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 (pcs->is_64bit) { - if (!ReadProcessMemory(pcs->handle, lm_addr, &lm, sizeof(lm), NULL)) - return FALSE; + struct r_debug dbg_hdr; + struct link_map lm; - 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)) + if (!pcs->dbg_hdr_addr || + !ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr, + &dbg_hdr, sizeof(dbg_hdr), NULL)) + return FALSE; + + /* 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) { - bufstr[sizeof(bufstr) - 1] = '\0'; - MultiByteToWideChar(CP_UNIXCP, 0, bufstr, -1, bufstrW, sizeof(bufstrW) / sizeof(WCHAR)); - if (main_name && !bufstrW[0]) strcpyW(bufstrW, main_name); - if (!cb(bufstrW, (unsigned long)lm.l_addr, (unsigned long)lm.l_ld, FALSE, user)) break; - } + 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'; + MultiByteToWideChar(CP_UNIXCP, 0, bufstr, -1, bufstrW, + sizeof(bufstrW) / sizeof(WCHAR)); + if (main_name && !bufstrW[0]) strcpyW(bufstrW, main_name); + if (!cb(bufstrW, (unsigned long)lm.l_addr, (unsigned long)lm.l_ld, FALSE, user)) + break; + } + } + } + else + { + struct r_debug32 dbg_hdr; + struct link_map32 lm; + + if (!pcs->dbg_hdr_addr || + !ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr, + &dbg_hdr, sizeof(dbg_hdr), NULL)) + return FALSE; + + /* 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 *)(DWORD_PTR)dbg_hdr.r_map; lm_addr; + lm_addr = (void *)(DWORD_PTR)lm.l_next) + { + if (!ReadProcessMemory(pcs->handle, lm_addr, &lm, sizeof(lm), NULL)) + return FALSE; + + if (lm.l_prev && /* skip first entry, normally debuggee itself */ + lm.l_name && + ReadProcessMemory(pcs->handle, (void *)(DWORD_PTR)lm.l_name, + bufstr, sizeof(bufstr), NULL)) + { + bufstr[sizeof(bufstr) - 1] = '\0'; + MultiByteToWideChar(CP_UNIXCP, 0, bufstr, -1, bufstrW, + sizeof(bufstrW) / sizeof(WCHAR)); + if (main_name && !bufstrW[0]) strcpyW(bufstrW, main_name); + if (!cb(bufstrW, (unsigned long)lm.l_addr, (unsigned long)lm.l_ld, FALSE, user)) + break; + } + } } #ifdef AT_SYSINFO_EHDR