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