Eric Pouech : dbghelp: For targets on Linux, report the VDSO system page as a known ELF module.
Alexandre Julliard
julliard at winehq.org
Tue Dec 28 10:48:18 CST 2010
Module: wine
Branch: master
Commit: 1966ba8b7f42c3fd2c286b2010af277eaebbe9c7
URL: http://source.winehq.org/git/wine.git/?a=commit;h=1966ba8b7f42c3fd2c286b2010af277eaebbe9c7
Author: Eric Pouech <eric.pouech at orange.fr>
Date: Mon Dec 27 15:03:36 2010 +0100
dbghelp: For targets on Linux, report the VDSO system page as a known ELF module.
---
dlls/dbghelp/elf_module.c | 92 +++++++++++++++++++++++++++++++++++++++--
dlls/dbghelp/image_private.h | 2 +
2 files changed, 89 insertions(+), 5 deletions(-)
diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c
index 305f420..2bfa2a4 100644
--- a/dlls/dbghelp/elf_module.c
+++ b/dlls/dbghelp/elf_module.c
@@ -1297,6 +1297,59 @@ static BOOL elf_load_file_from_dll_path(HANDLE hProcess,
return ret;
}
+#ifdef AT_SYSINFO_EHDR
+/******************************************************************
+ * elf_search_auxv
+ *
+ * locate some a value from the debuggee auxillary vector
+ */
+static BOOL elf_search_auxv(const struct process* pcs, unsigned type, unsigned long* val)
+{
+ char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
+ SYMBOL_INFO*si = (SYMBOL_INFO*)buffer;
+ void* addr;
+ void* str;
+ void* str_max;
+ Elf_auxv_t auxv;
+
+ si->SizeOfStruct = sizeof(*si);
+ si->MaxNameLen = MAX_SYM_NAME;
+ if (!SymFromName(pcs->handle, "libwine.so.1!__wine_main_environ", si) ||
+ !(addr = (void*)(DWORD_PTR)si->Address) ||
+ !ReadProcessMemory(pcs->handle, addr, &addr, sizeof(addr), NULL) ||
+ !addr)
+ {
+ FIXME("can't find symbol in module\n");
+ return FALSE;
+ }
+ /* walk through envp[] */
+ /* envp[] strings are located after the auxillary vector, so protect the walk */
+ str_max = (void*)(DWORD_PTR)~0L;
+ while (ReadProcessMemory(pcs->handle, addr, &str, sizeof(str), NULL) &&
+ (addr = (void*)((DWORD_PTR)addr + sizeof(str))) != NULL && str != NULL)
+ str_max = min(str_max, str);
+
+ /* Walk through the end of envp[] array.
+ * Actually, there can be several NULLs at the end of envp[]. This happens when an env variable is
+ * deleted, the last entry is replaced by an extra NULL.
+ */
+ while (addr < str_max && ReadProcessMemory(pcs->handle, addr, &str, sizeof(str), NULL) && str == NULL)
+ addr = (void*)((DWORD_PTR)addr + sizeof(str));
+
+ while (ReadProcessMemory(pcs->handle, addr, &auxv, sizeof(auxv), NULL) && auxv.a_type != AT_NULL)
+ {
+ if (auxv.a_type == type)
+ {
+ *val = auxv.a_un.a_val;
+ return TRUE;
+ }
+ addr = (void*)((DWORD_PTR)addr + sizeof(auxv));
+ }
+
+ return FALSE;
+}
+#endif
+
/******************************************************************
* elf_search_and_load_file
*
@@ -1330,12 +1383,12 @@ static BOOL elf_search_and_load_file(struct process* pcs, const WCHAR* filename,
if (!ret) ret = elf_load_file_from_dll_path(pcs, filename,
load_offset, dyn_addr, elf_info);
}
-
+
return ret;
}
typedef BOOL (*enum_elf_modules_cb)(const WCHAR*, unsigned long load_addr,
- unsigned long dyn_addr, void* user);
+ unsigned long dyn_addr, BOOL is_system, void* user);
/******************************************************************
* elf_enum_modules_internal
@@ -1351,6 +1404,7 @@ static BOOL elf_enum_modules_internal(const struct process* pcs,
struct link_map lm;
char bufstr[256];
WCHAR bufstrW[MAX_PATH];
+ unsigned long ehdr_addr;
if (!pcs->dbg_hdr_addr ||
!ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr,
@@ -1374,9 +1428,16 @@ static BOOL elf_enum_modules_internal(const struct process* pcs,
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, user)) break;
+ if (!cb(bufstrW, (unsigned long)lm.l_addr, (unsigned long)lm.l_ld, FALSE, user)) break;
}
}
+#ifdef AT_SYSINFO_EHDR
+ if (!lm_addr && elf_search_auxv(pcs, AT_SYSINFO_EHDR, &ehdr_addr))
+ {
+ static const WCHAR vdsoW[] = {'[','v','d','s','o',']','.','s','o',0};
+ cb(vdsoW, ehdr_addr, 0, TRUE, user);
+ }
+#endif
return TRUE;
}
@@ -1432,7 +1493,7 @@ struct elf_enum_user
};
static BOOL elf_enum_modules_translate(const WCHAR* name, unsigned long load_addr,
- unsigned long dyn_addr, void* user)
+ unsigned long dyn_addr, BOOL is_system, void* user)
{
struct elf_enum_user* eeu = user;
return eeu->cb(name, load_addr, eeu->user);
@@ -1479,12 +1540,33 @@ struct elf_load
* modules.
*/
static BOOL elf_load_cb(const WCHAR* name, unsigned long load_addr,
- unsigned long dyn_addr, void* user)
+ unsigned long dyn_addr, BOOL is_system, void* user)
{
struct elf_load* el = user;
BOOL ret = TRUE;
const WCHAR* p;
+ if (is_system) /* virtual ELF module, created by system. handle it from memory */
+ {
+ struct module* module;
+ struct elf_map_file_data emfd;
+ struct image_file_map fmap;
+
+ if ((module = module_is_already_loaded(el->pcs, name)))
+ {
+ el->elf_info.module = module;
+ el->elf_info.module->format_info[DFI_ELF]->u.elf_info->elf_mark = 1;
+ return module->module.SymType;
+ }
+
+ emfd.kind = from_process;
+ emfd.u.process.handle = el->pcs->handle;
+ emfd.u.process.load_addr = (void*)load_addr;
+
+ if (elf_map_file(&emfd, &fmap))
+ el->ret = elf_load_file_from_fmap(el->pcs, name, &fmap, load_addr, 0, &el->elf_info);
+ return TRUE;
+ }
if (el->name)
{
/* memcmp is needed for matches when bufstr contains also version information
diff --git a/dlls/dbghelp/image_private.h b/dlls/dbghelp/image_private.h
index 34e2c18..23a05da 100644
--- a/dlls/dbghelp/image_private.h
+++ b/dlls/dbghelp/image_private.h
@@ -53,12 +53,14 @@
#define Elf_Phdr Elf64_Phdr
#define Elf_Dyn Elf64_Dyn
#define Elf_Sym Elf64_Sym
+#define Elf_auxv_t Elf64_auxv_t
#else
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Shdr Elf32_Shdr
#define Elf_Phdr Elf32_Phdr
#define Elf_Dyn Elf32_Dyn
#define Elf_Sym Elf32_Sym
+#define Elf_auxv_t Elf32_auxv_t
#endif
#else
#ifndef SHT_NULL
More information about the wine-cvs
mailing list