[libunwind] r315498 - Support DWARF unwinding on i386 windows

Martin Storsjo via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 11 13:06:18 PDT 2017


Author: mstorsjo
Date: Wed Oct 11 13:06:18 2017
New Revision: 315498

URL: http://llvm.org/viewvc/llvm-project?rev=315498&view=rev
Log:
Support DWARF unwinding on i386 windows

In practice, with code built with clang, there are still unresolved
issues with DW_CFA_GNU_args_size though.

Differential Revision: https://reviews.llvm.org/D38679

Modified:
    libunwind/trunk/src/AddressSpace.hpp
    libunwind/trunk/src/UnwindRegistersRestore.S
    libunwind/trunk/src/assembly.h
    libunwind/trunk/src/config.h

Modified: libunwind/trunk/src/AddressSpace.hpp
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/AddressSpace.hpp?rev=315498&r1=315497&r2=315498&view=diff
==============================================================================
--- libunwind/trunk/src/AddressSpace.hpp (original)
+++ libunwind/trunk/src/AddressSpace.hpp Wed Oct 11 13:06:18 2017
@@ -18,7 +18,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#ifndef _LIBUNWIND_IS_BAREMETAL
+#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
 #include <dlfcn.h>
 #endif
 
@@ -97,7 +97,12 @@ extern char __exidx_end;
 // independent ELF header traversal is not provided by <link.h> on some
 // systems (e.g., FreeBSD). On these systems the data structures are
 // just called Elf_XXX. Define ElfW() locally.
+#ifndef _WIN32
 #include <link.h>
+#else
+#include <windows.h>
+#include <psapi.h>
+#endif
 #if !defined(ElfW)
 #define ElfW(type) Elf_##type
 #endif
@@ -356,6 +361,43 @@ inline bool LocalAddressSpace::findUnwin
                              info.arm_section, info.arm_section_length);
   if (info.arm_section && info.arm_section_length)
     return true;
+#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
+  HMODULE mods[1024];
+  HANDLE process = GetCurrentProcess();
+  DWORD needed;
+
+  if (!EnumProcessModules(process, mods, sizeof(mods), &needed))
+    return false;
+
+  for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) {
+    PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i];
+    PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew);
+    PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
+    PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh);
+    bool found_obj = false;
+    bool found_hdr = false;
+
+    info.dso_base = (uintptr_t)mods[i];
+    for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) {
+      uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i];
+      uintptr_t end = begin + pish->Misc.VirtualSize;
+      if (!strncmp((const char *)pish->Name, ".text",
+                   IMAGE_SIZEOF_SHORT_NAME)) {
+        if (targetAddr >= begin && targetAddr < end)
+          found_obj = true;
+      } else if (!strncmp((const char *)pish->Name, ".eh_frame",
+                          IMAGE_SIZEOF_SHORT_NAME)) {
+        // FIXME: This section name actually is truncated, ideally we
+        // should locate and check the full long name instead.
+        info.dwarf_section = begin;
+        info.dwarf_section_length = pish->Misc.VirtualSize;
+        found_hdr = true;
+      }
+      if (found_obj && found_hdr)
+        return true;
+    }
+  }
+  return false;
 #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
   struct dl_iterate_cb_data {
     LocalAddressSpace *addressSpace;
@@ -478,7 +520,7 @@ inline bool LocalAddressSpace::findOther
 inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
                                                 size_t bufLen,
                                                 unw_word_t *offset) {
-#ifndef _LIBUNWIND_IS_BAREMETAL
+#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
   Dl_info dyldInfo;
   if (dladdr((void *)addr, &dyldInfo)) {
     if (dyldInfo.dli_sname != NULL) {

Modified: libunwind/trunk/src/UnwindRegistersRestore.S
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/UnwindRegistersRestore.S?rev=315498&r1=315497&r2=315498&view=diff
==============================================================================
--- libunwind/trunk/src/UnwindRegistersRestore.S (original)
+++ libunwind/trunk/src/UnwindRegistersRestore.S Wed Oct 11 13:06:18 2017
@@ -18,6 +18,10 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9li
 #
 # void libunwind::Registers_x86::jumpto()
 #
+#if defined(_WIN32)
+# On windows, the 'this' pointer is passed in ecx instead of on the stack
+  movl   %ecx, %eax
+#else
 # On entry:
 #  +                       +
 #  +-----------------------+
@@ -27,6 +31,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9li
 #  +-----------------------+   <-- SP
 #  +                       +
   movl   4(%esp), %eax
+#endif
   # set up eax and ret on new stack location
   movl  28(%eax), %edx # edx holds new stack pointer
   subl  $8,%edx

Modified: libunwind/trunk/src/assembly.h
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/assembly.h?rev=315498&r1=315497&r2=315498&view=diff
==============================================================================
--- libunwind/trunk/src/assembly.h (original)
+++ libunwind/trunk/src/assembly.h Wed Oct 11 13:06:18 2017
@@ -26,6 +26,14 @@
 
 #if defined(__APPLE__)
 #define HIDDEN_DIRECTIVE .private_extern
+#elif defined(_WIN32)
+// In the COFF object file format, there's no attributes for a global,
+// non-static symbol to make it somehow hidden. So on windows, we don't
+// want to set this at all. To avoid conditionals in
+// DEFINE_LIBUNWIND_PRIVATE_FUNCTION below, make it .globl (which it already
+// is, defined in the same DEFINE_LIBUNWIND_PRIVATE_FUNCTION macro; the
+// duplicate .globl directives are harmless).
+#define HIDDEN_DIRECTIVE .globl
 #else
 #define HIDDEN_DIRECTIVE .hidden
 #endif

Modified: libunwind/trunk/src/config.h
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/config.h?rev=315498&r1=315497&r2=315498&view=diff
==============================================================================
--- libunwind/trunk/src/config.h (original)
+++ libunwind/trunk/src/config.h Wed Oct 11 13:06:18 2017
@@ -37,6 +37,8 @@
     #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND
     #define _LIBUNWIND_SUPPORT_DWARF_UNWIND   1
   #endif
+#elif defined(_WIN32)
+  #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
 #else
   #if defined(__ARM_DWARF_EH__) || !defined(__arm__)
     #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1




More information about the cfe-commits mailing list