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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits