[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