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

llvm-svn: 315498
This commit is contained in:
Martin Storsjo 2017-10-11 20:06:18 +00:00
parent b03f480c8d
commit 210d9f43a3
4 changed files with 59 additions and 2 deletions

View File

@ -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::findUnwindSections(pint_t targetAddr,
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::findOtherFDE(pint_t targetAddr, pint_t &fde) {
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) {

View File

@ -18,6 +18,10 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv)
#
# 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(_ZN9libunwind13Registers_x866jumptoEv)
# +-----------------------+ <-- 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

View File

@ -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

View File

@ -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