Index: head/contrib/libunwind/src/AddressSpace.hpp =================================================================== --- head/contrib/libunwind/src/AddressSpace.hpp (nonexistent) +++ head/contrib/libunwind/src/AddressSpace.hpp (revision 345068) @@ -0,0 +1,738 @@ +//===------------------------- AddressSpace.hpp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Abstracts accessing local vs remote address spaces. +// +//===----------------------------------------------------------------------===// + +#ifndef __ADDRESSSPACE_HPP__ +#define __ADDRESSSPACE_HPP__ + +#include +#include +#include +#include + +#ifndef _LIBUNWIND_USE_DLADDR + #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) + #define _LIBUNWIND_USE_DLADDR 1 + #else + #define _LIBUNWIND_USE_DLADDR 0 + #endif +#endif + +#if _LIBUNWIND_USE_DLADDR +#include +#endif + +#ifdef __APPLE__ +#include +namespace libunwind { + bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde); +} +#endif + +#include "libunwind.h" +#include "config.h" +#include "dwarf2.h" +#include "EHHeaderParser.hpp" +#include "Registers.hpp" + +#ifdef __APPLE__ + + struct dyld_unwind_sections + { + const struct mach_header* mh; + const void* dwarf_section; + uintptr_t dwarf_section_length; + const void* compact_unwind_section; + uintptr_t compact_unwind_section_length; + }; + #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \ + && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \ + || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) + // In 10.7.0 or later, libSystem.dylib implements this function. + extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *); + #else + // In 10.6.x and earlier, we need to implement this functionality. Note + // that this requires a newer version of libmacho (from cctools) than is + // present in libSystem on 10.6.x (for getsectiondata). + static inline bool _dyld_find_unwind_sections(void* addr, + dyld_unwind_sections* info) { + // Find mach-o image containing address. + Dl_info dlinfo; + if (!dladdr(addr, &dlinfo)) + return false; +#if __LP64__ + const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase; +#else + const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase; +#endif + + // Initialize the return struct + info->mh = (const struct mach_header *)mh; + info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length); + info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length); + + if (!info->dwarf_section) { + info->dwarf_section_length = 0; + } + + if (!info->compact_unwind_section) { + info->compact_unwind_section_length = 0; + } + + return true; + } + #endif + +#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) + +// When statically linked on bare-metal, the symbols for the EH table are looked +// up without going through the dynamic loader. + +// The following linker script may be used to produce the necessary sections and symbols. +// Unless the --eh-frame-hdr linker option is provided, the section is not generated +// and does not take space in the output file. +// +// .eh_frame : +// { +// __eh_frame_start = .; +// KEEP(*(.eh_frame)) +// __eh_frame_end = .; +// } +// +// .eh_frame_hdr : +// { +// KEEP(*(.eh_frame_hdr)) +// } +// +// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; +// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; + +extern char __eh_frame_start; +extern char __eh_frame_end; + +#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) +extern char __eh_frame_hdr_start; +extern char __eh_frame_hdr_end; +#endif + +#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) + +// When statically linked on bare-metal, the symbols for the EH table are looked +// up without going through the dynamic loader. +extern char __exidx_start; +extern char __exidx_end; + +#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + +// ELF-based systems may use dl_iterate_phdr() to access sections +// containing unwinding information. The ElfW() macro for pointer-size +// independent ELF header traversal is not provided by on some +// systems (e.g., FreeBSD). On these systems the data structures are +// just called Elf_XXX. Define ElfW() locally. +#ifndef _WIN32 +#include +#else +#include +#include +#endif +#if !defined(ElfW) +#define ElfW(type) Elf_##type +#endif + +#endif + +namespace libunwind { + +/// Used by findUnwindSections() to return info about needed sections. +struct UnwindInfoSections { +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \ + defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) + // No dso_base for SEH or ARM EHABI. + uintptr_t dso_base; +#endif +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + uintptr_t dwarf_section; + uintptr_t dwarf_section_length; +#endif +#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + uintptr_t dwarf_index_section; + uintptr_t dwarf_index_section_length; +#endif +#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) + uintptr_t compact_unwind_section; + uintptr_t compact_unwind_section_length; +#endif +#if defined(_LIBUNWIND_ARM_EHABI) + uintptr_t arm_section; + uintptr_t arm_section_length; +#endif +}; + + +/// LocalAddressSpace is used as a template parameter to UnwindCursor when +/// unwinding a thread in the same process. The wrappers compile away, +/// making local unwinds fast. +class _LIBUNWIND_HIDDEN LocalAddressSpace { +public: + typedef uintptr_t pint_t; + typedef intptr_t sint_t; + uint8_t get8(pint_t addr) { + uint8_t val; + memcpy(&val, (void *)addr, sizeof(val)); + return val; + } + uint16_t get16(pint_t addr) { + uint16_t val; + memcpy(&val, (void *)addr, sizeof(val)); + return val; + } + uint32_t get32(pint_t addr) { + uint32_t val; + memcpy(&val, (void *)addr, sizeof(val)); + return val; + } + uint64_t get64(pint_t addr) { + uint64_t val; + memcpy(&val, (void *)addr, sizeof(val)); + return val; + } + double getDouble(pint_t addr) { + double val; + memcpy(&val, (void *)addr, sizeof(val)); + return val; + } + v128 getVector(pint_t addr) { + v128 val; + memcpy(&val, (void *)addr, sizeof(val)); + return val; + } + uintptr_t getP(pint_t addr); + uint64_t getRegister(pint_t addr); + static uint64_t getULEB128(pint_t &addr, pint_t end); + static int64_t getSLEB128(pint_t &addr, pint_t end); + + pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, + pint_t datarelBase = 0); + bool findFunctionName(pint_t addr, char *buf, size_t bufLen, + unw_word_t *offset); + bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); + bool findOtherFDE(pint_t targetAddr, pint_t &fde); + + static LocalAddressSpace sThisAddressSpace; +}; + +inline uintptr_t LocalAddressSpace::getP(pint_t addr) { +#if __SIZEOF_POINTER__ == 8 + return get64(addr); +#else + return get32(addr); +#endif +} + +inline uint64_t LocalAddressSpace::getRegister(pint_t addr) { +#if __SIZEOF_POINTER__ == 8 || defined(__mips64) + return get64(addr); +#else + return get32(addr); +#endif +} + +/// Read a ULEB128 into a 64-bit word. +inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) { + const uint8_t *p = (uint8_t *)addr; + const uint8_t *pend = (uint8_t *)end; + uint64_t result = 0; + int bit = 0; + do { + uint64_t b; + + if (p == pend) + _LIBUNWIND_ABORT("truncated uleb128 expression"); + + b = *p & 0x7f; + + if (bit >= 64 || b << bit >> bit != b) { + _LIBUNWIND_ABORT("malformed uleb128 expression"); + } else { + result |= b << bit; + bit += 7; + } + } while (*p++ >= 0x80); + addr = (pint_t) p; + return result; +} + +/// Read a SLEB128 into a 64-bit word. +inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { + const uint8_t *p = (uint8_t *)addr; + const uint8_t *pend = (uint8_t *)end; + int64_t result = 0; + int bit = 0; + uint8_t byte; + do { + if (p == pend) + _LIBUNWIND_ABORT("truncated sleb128 expression"); + byte = *p++; + result |= ((byte & 0x7f) << bit); + bit += 7; + } while (byte & 0x80); + // sign extend negative numbers + if ((byte & 0x40) != 0) + result |= (-1ULL) << bit; + addr = (pint_t) p; + return result; +} + +inline LocalAddressSpace::pint_t +LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, + pint_t datarelBase) { + pint_t startAddr = addr; + const uint8_t *p = (uint8_t *)addr; + pint_t result; + + // first get value + switch (encoding & 0x0F) { + case DW_EH_PE_ptr: + result = getP(addr); + p += sizeof(pint_t); + addr = (pint_t) p; + break; + case DW_EH_PE_uleb128: + result = (pint_t)getULEB128(addr, end); + break; + case DW_EH_PE_udata2: + result = get16(addr); + p += 2; + addr = (pint_t) p; + break; + case DW_EH_PE_udata4: + result = get32(addr); + p += 4; + addr = (pint_t) p; + break; + case DW_EH_PE_udata8: + result = (pint_t)get64(addr); + p += 8; + addr = (pint_t) p; + break; + case DW_EH_PE_sleb128: + result = (pint_t)getSLEB128(addr, end); + break; + case DW_EH_PE_sdata2: + // Sign extend from signed 16-bit value. + result = (pint_t)(int16_t)get16(addr); + p += 2; + addr = (pint_t) p; + break; + case DW_EH_PE_sdata4: + // Sign extend from signed 32-bit value. + result = (pint_t)(int32_t)get32(addr); + p += 4; + addr = (pint_t) p; + break; + case DW_EH_PE_sdata8: + result = (pint_t)get64(addr); + p += 8; + addr = (pint_t) p; + break; + default: + _LIBUNWIND_ABORT("unknown pointer encoding"); + } + + // then add relative offset + switch (encoding & 0x70) { + case DW_EH_PE_absptr: + // do nothing + break; + case DW_EH_PE_pcrel: + result += startAddr; + break; + case DW_EH_PE_textrel: + _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported"); + break; + case DW_EH_PE_datarel: + // DW_EH_PE_datarel is only valid in a few places, so the parameter has a + // default value of 0, and we abort in the event that someone calls this + // function with a datarelBase of 0 and DW_EH_PE_datarel encoding. + if (datarelBase == 0) + _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0"); + result += datarelBase; + break; + case DW_EH_PE_funcrel: + _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported"); + break; + case DW_EH_PE_aligned: + _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported"); + break; + default: + _LIBUNWIND_ABORT("unknown pointer encoding"); + break; + } + + if (encoding & DW_EH_PE_indirect) + result = getP(result); + + return result; +} + +inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, + UnwindInfoSections &info) { +#ifdef __APPLE__ + dyld_unwind_sections dyldInfo; + if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { + info.dso_base = (uintptr_t)dyldInfo.mh; + #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section; + info.dwarf_section_length = dyldInfo.dwarf_section_length; + #endif + info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section; + info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length; + return true; + } +#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) + // Bare metal is statically linked, so no need to ask the dynamic loader + info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start); + info.dwarf_section = (uintptr_t)(&__eh_frame_start); + _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", + (void *)info.dwarf_section, (void *)info.dwarf_section_length); +#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start); + info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start); + _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p", + (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length); +#endif + if (info.dwarf_section_length) + return true; +#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) + // Bare metal is statically linked, so no need to ask the dynamic loader + info.arm_section = (uintptr_t)(&__exidx_start); + info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start); + _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", + (void *)info.arm_section, (void *)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)) { + 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_SUPPORT_SEH_UNWIND) && defined(_WIN32) + // Don't even bother, since Windows has functions that do all this stuff + // for us. + return true; +#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) && \ + (__ANDROID_API__ < 21) + int length = 0; + info.arm_section = + (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); + info.arm_section_length = (uintptr_t)length; + if (info.arm_section && info.arm_section_length) + return true; +#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + struct dl_iterate_cb_data { + LocalAddressSpace *addressSpace; + UnwindInfoSections *sects; + uintptr_t targetAddr; + }; + + dl_iterate_cb_data cb_data = {this, &info, targetAddr}; + int found = dl_iterate_phdr( + [](struct dl_phdr_info *pinfo, size_t, void *data) -> int { + auto cbdata = static_cast(data); + bool found_obj = false; + bool found_hdr = false; + + assert(cbdata); + assert(cbdata->sects); + + if (cbdata->targetAddr < pinfo->dlpi_addr) { + return false; + } + +#if !defined(Elf_Half) + typedef ElfW(Half) Elf_Half; +#endif +#if !defined(Elf_Phdr) + typedef ElfW(Phdr) Elf_Phdr; +#endif +#if !defined(Elf_Addr) && defined(__ANDROID__) + typedef ElfW(Addr) Elf_Addr; +#endif + + #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." + #endif + size_t object_length; +#if defined(__ANDROID__) + Elf_Addr image_base = + pinfo->dlpi_phnum + ? reinterpret_cast(pinfo->dlpi_phdr) - + reinterpret_cast(pinfo->dlpi_phdr) + ->p_offset + : 0; +#endif + + for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { + const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; + if (phdr->p_type == PT_LOAD) { + uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; +#if defined(__ANDROID__) + if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base) + begin = begin + image_base; +#endif + uintptr_t end = begin + phdr->p_memsz; + if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { + cbdata->sects->dso_base = begin; + object_length = phdr->p_memsz; + found_obj = true; + } + } else if (phdr->p_type == PT_GNU_EH_FRAME) { + EHHeaderParser::EHHeaderInfo hdrInfo; + uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr; +#if defined(__ANDROID__) + if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base) + eh_frame_hdr_start = eh_frame_hdr_start + image_base; +#endif + cbdata->sects->dwarf_index_section = eh_frame_hdr_start; + cbdata->sects->dwarf_index_section_length = phdr->p_memsz; + found_hdr = EHHeaderParser::decodeEHHdr( + *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, + hdrInfo); + if (found_hdr) + cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; + } + } + + if (found_obj && found_hdr) { + cbdata->sects->dwarf_section_length = object_length; + return true; + } else { + return false; + } + #else // defined(_LIBUNWIND_ARM_EHABI) + for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { + const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; + if (phdr->p_type == PT_LOAD) { + uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; + uintptr_t end = begin + phdr->p_memsz; + if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) + found_obj = true; + } else if (phdr->p_type == PT_ARM_EXIDX) { + uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr; + cbdata->sects->arm_section = exidx_start; + cbdata->sects->arm_section_length = phdr->p_memsz; + found_hdr = true; + } + } + return found_obj && found_hdr; + #endif + }, + &cb_data); + return static_cast(found); +#endif + + return false; +} + + +inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { +#ifdef __APPLE__ + return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde)); +#else + // TO DO: if OS has way to dynamically register FDEs, check that. + (void)targetAddr; + (void)fde; + return false; +#endif +} + +inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, + size_t bufLen, + unw_word_t *offset) { +#if _LIBUNWIND_USE_DLADDR + Dl_info dyldInfo; + if (dladdr((void *)addr, &dyldInfo)) { + if (dyldInfo.dli_sname != NULL) { + snprintf(buf, bufLen, "%s", dyldInfo.dli_sname); + *offset = (addr - (pint_t) dyldInfo.dli_saddr); + return true; + } + } +#endif + return false; +} + + + +#ifdef UNW_REMOTE + +/// RemoteAddressSpace is used as a template parameter to UnwindCursor when +/// unwinding a thread in the another process. The other process can be a +/// different endianness and a different pointer size which is handled by +/// the P template parameter. +template +class RemoteAddressSpace { +public: + RemoteAddressSpace(task_t task) : fTask(task) {} + + typedef typename P::uint_t pint_t; + + uint8_t get8(pint_t addr); + uint16_t get16(pint_t addr); + uint32_t get32(pint_t addr); + uint64_t get64(pint_t addr); + pint_t getP(pint_t addr); + uint64_t getRegister(pint_t addr); + uint64_t getULEB128(pint_t &addr, pint_t end); + int64_t getSLEB128(pint_t &addr, pint_t end); + pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, + pint_t datarelBase = 0); + bool findFunctionName(pint_t addr, char *buf, size_t bufLen, + unw_word_t *offset); + bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); + bool findOtherFDE(pint_t targetAddr, pint_t &fde); +private: + void *localCopy(pint_t addr); + + task_t fTask; +}; + +template uint8_t RemoteAddressSpace

::get8(pint_t addr) { + return *((uint8_t *)localCopy(addr)); +} + +template uint16_t RemoteAddressSpace

::get16(pint_t addr) { + return P::E::get16(*(uint16_t *)localCopy(addr)); +} + +template uint32_t RemoteAddressSpace

::get32(pint_t addr) { + return P::E::get32(*(uint32_t *)localCopy(addr)); +} + +template uint64_t RemoteAddressSpace

::get64(pint_t addr) { + return P::E::get64(*(uint64_t *)localCopy(addr)); +} + +template +typename P::uint_t RemoteAddressSpace

::getP(pint_t addr) { + return P::getP(*(uint64_t *)localCopy(addr)); +} + +template +typename P::uint_t OtherAddressSpace

::getRegister(pint_t addr) { + return P::getRegister(*(uint64_t *)localCopy(addr)); +} + +template +uint64_t OtherAddressSpace

::getULEB128(pint_t &addr, pint_t end) { + uintptr_t size = (end - addr); + LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); + LocalAddressSpace::pint_t sladdr = laddr; + uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size); + addr += (laddr - sladdr); + return result; +} + +template +int64_t RemoteAddressSpace

::getSLEB128(pint_t &addr, pint_t end) { + uintptr_t size = (end - addr); + LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); + LocalAddressSpace::pint_t sladdr = laddr; + uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size); + addr += (laddr - sladdr); + return result; +} + +template void *RemoteAddressSpace

::localCopy(pint_t addr) { + // FIX ME +} + +template +bool RemoteAddressSpace

::findFunctionName(pint_t addr, char *buf, + size_t bufLen, + unw_word_t *offset) { + // FIX ME +} + +/// unw_addr_space is the base class that abstract unw_addr_space_t type in +/// libunwind.h points to. +struct unw_addr_space { + cpu_type_t cpuType; + task_t taskPort; +}; + +/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points +/// to when examining +/// a 32-bit intel process. +struct unw_addr_space_i386 : public unw_addr_space { + unw_addr_space_i386(task_t task) : oas(task) {} + RemoteAddressSpace> oas; +}; + +/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t +/// points to when examining +/// a 64-bit intel process. +struct unw_addr_space_x86_64 : public unw_addr_space { + unw_addr_space_x86_64(task_t task) : oas(task) {} + RemoteAddressSpace> oas; +}; + +/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points +/// to when examining +/// a 32-bit PowerPC process. +struct unw_addr_space_ppc : public unw_addr_space { + unw_addr_space_ppc(task_t task) : oas(task) {} + RemoteAddressSpace> oas; +}; + +/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points +/// to when examining a 64-bit PowerPC process. +struct unw_addr_space_ppc64 : public unw_addr_space { + unw_addr_space_ppc64(task_t task) : oas(task) {} + RemoteAddressSpace> oas; +}; + +#endif // UNW_REMOTE + +} // namespace libunwind + +#endif // __ADDRESSSPACE_HPP__ Index: head/contrib/libunwind/src/EHHeaderParser.hpp =================================================================== --- head/contrib/libunwind/src/EHHeaderParser.hpp (nonexistent) +++ head/contrib/libunwind/src/EHHeaderParser.hpp (revision 345068) @@ -0,0 +1,168 @@ +//===------------------------- EHHeaderParser.hpp -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Parses ELF .eh_frame_hdr sections. +// +//===----------------------------------------------------------------------===// + +#ifndef __EHHEADERPARSER_HPP__ +#define __EHHEADERPARSER_HPP__ + +#include "libunwind.h" + +#include "DwarfParser.hpp" + +namespace libunwind { + +/// \brief EHHeaderParser does basic parsing of an ELF .eh_frame_hdr section. +/// +/// See DWARF spec for details: +/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html +/// +template class EHHeaderParser { +public: + typedef typename A::pint_t pint_t; + + /// Information encoded in the EH frame header. + struct EHHeaderInfo { + pint_t eh_frame_ptr; + size_t fde_count; + pint_t table; + uint8_t table_enc; + }; + + static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, + EHHeaderInfo &ehHdrInfo); + static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, + uint32_t sectionLength, + typename CFI_Parser::FDE_Info *fdeInfo, + typename CFI_Parser::CIE_Info *cieInfo); + +private: + static bool decodeTableEntry(A &addressSpace, pint_t &tableEntry, + pint_t ehHdrStart, pint_t ehHdrEnd, + uint8_t tableEnc, + typename CFI_Parser::FDE_Info *fdeInfo, + typename CFI_Parser::CIE_Info *cieInfo); + static size_t getTableEntrySize(uint8_t tableEnc); +}; + +template +bool EHHeaderParser::decodeEHHdr(A &addressSpace, pint_t ehHdrStart, + pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) { + pint_t p = ehHdrStart; + uint8_t version = addressSpace.get8(p++); + if (version != 1) { + _LIBUNWIND_LOG0("Unsupported .eh_frame_hdr version"); + return false; + } + + uint8_t eh_frame_ptr_enc = addressSpace.get8(p++); + uint8_t fde_count_enc = addressSpace.get8(p++); + ehHdrInfo.table_enc = addressSpace.get8(p++); + + ehHdrInfo.eh_frame_ptr = + addressSpace.getEncodedP(p, ehHdrEnd, eh_frame_ptr_enc, ehHdrStart); + ehHdrInfo.fde_count = + fde_count_enc == DW_EH_PE_omit + ? 0 + : addressSpace.getEncodedP(p, ehHdrEnd, fde_count_enc, ehHdrStart); + ehHdrInfo.table = p; + + return true; +} + +template +bool EHHeaderParser::decodeTableEntry( + A &addressSpace, pint_t &tableEntry, pint_t ehHdrStart, pint_t ehHdrEnd, + uint8_t tableEnc, typename CFI_Parser::FDE_Info *fdeInfo, + typename CFI_Parser::CIE_Info *cieInfo) { + // Have to decode the whole FDE for the PC range anyway, so just throw away + // the PC start. + addressSpace.getEncodedP(tableEntry, ehHdrEnd, tableEnc, ehHdrStart); + pint_t fde = + addressSpace.getEncodedP(tableEntry, ehHdrEnd, tableEnc, ehHdrStart); + const char *message = + CFI_Parser::decodeFDE(addressSpace, fde, fdeInfo, cieInfo); + if (message != NULL) { + _LIBUNWIND_DEBUG_LOG("EHHeaderParser::decodeTableEntry: bad fde: %s", + message); + return false; + } + + return true; +} + +template +bool EHHeaderParser::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, + uint32_t sectionLength, + typename CFI_Parser::FDE_Info *fdeInfo, + typename CFI_Parser::CIE_Info *cieInfo) { + pint_t ehHdrEnd = ehHdrStart + sectionLength; + + EHHeaderParser::EHHeaderInfo hdrInfo; + if (!EHHeaderParser::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd, + hdrInfo)) + return false; + + size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc); + pint_t tableEntry; + + size_t low = 0; + for (size_t len = hdrInfo.fde_count; len > 1;) { + size_t mid = low + (len / 2); + tableEntry = hdrInfo.table + mid * tableEntrySize; + pint_t start = addressSpace.getEncodedP(tableEntry, ehHdrEnd, + hdrInfo.table_enc, ehHdrStart); + + if (start == pc) { + low = mid; + break; + } else if (start < pc) { + low = mid; + len -= (len / 2); + } else { + len /= 2; + } + } + + tableEntry = hdrInfo.table + low * tableEntrySize; + if (decodeTableEntry(addressSpace, tableEntry, ehHdrStart, ehHdrEnd, + hdrInfo.table_enc, fdeInfo, cieInfo)) { + if (pc >= fdeInfo->pcStart && pc < fdeInfo->pcEnd) + return true; + } + + return false; +} + +template +size_t EHHeaderParser::getTableEntrySize(uint8_t tableEnc) { + switch (tableEnc & 0x0f) { + case DW_EH_PE_sdata2: + case DW_EH_PE_udata2: + return 4; + case DW_EH_PE_sdata4: + case DW_EH_PE_udata4: + return 8; + case DW_EH_PE_sdata8: + case DW_EH_PE_udata8: + return 16; + case DW_EH_PE_sleb128: + case DW_EH_PE_uleb128: + _LIBUNWIND_ABORT("Can't binary search on variable length encoded data."); + case DW_EH_PE_omit: + return 0; + default: + _LIBUNWIND_ABORT("Unknown DWARF encoding for search table."); + } +} + +} + +#endif Index: head/contrib/libunwind/src/CompactUnwinder.hpp =================================================================== --- head/contrib/libunwind/src/CompactUnwinder.hpp (nonexistent) +++ head/contrib/libunwind/src/CompactUnwinder.hpp (revision 345068) @@ -0,0 +1,698 @@ +//===-------------------------- CompactUnwinder.hpp -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Does runtime stack unwinding using compact unwind encodings. +// +//===----------------------------------------------------------------------===// + +#ifndef __COMPACT_UNWINDER_HPP__ +#define __COMPACT_UNWINDER_HPP__ + +#include +#include + +#include +#include + +#include "Registers.hpp" + +#define EXTRACT_BITS(value, mask) \ + ((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1)) + +namespace libunwind { + +#if defined(_LIBUNWIND_TARGET_I386) +/// CompactUnwinder_x86 uses a compact unwind info to virtually "step" (aka +/// unwind) by modifying a Registers_x86 register set +template +class CompactUnwinder_x86 { +public: + + static int stepWithCompactEncoding(compact_unwind_encoding_t info, + uint32_t functionStart, A &addressSpace, + Registers_x86 ®isters); + +private: + typename A::pint_t pint_t; + + static void frameUnwind(A &addressSpace, Registers_x86 ®isters); + static void framelessUnwind(A &addressSpace, + typename A::pint_t returnAddressLocation, + Registers_x86 ®isters); + static int + stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding, + uint32_t functionStart, A &addressSpace, + Registers_x86 ®isters); + static int stepWithCompactEncodingFrameless( + compact_unwind_encoding_t compactEncoding, uint32_t functionStart, + A &addressSpace, Registers_x86 ®isters, bool indirectStackSize); +}; + +template +int CompactUnwinder_x86::stepWithCompactEncoding( + compact_unwind_encoding_t compactEncoding, uint32_t functionStart, + A &addressSpace, Registers_x86 ®isters) { + switch (compactEncoding & UNWIND_X86_MODE_MASK) { + case UNWIND_X86_MODE_EBP_FRAME: + return stepWithCompactEncodingEBPFrame(compactEncoding, functionStart, + addressSpace, registers); + case UNWIND_X86_MODE_STACK_IMMD: + return stepWithCompactEncodingFrameless(compactEncoding, functionStart, + addressSpace, registers, false); + case UNWIND_X86_MODE_STACK_IND: + return stepWithCompactEncodingFrameless(compactEncoding, functionStart, + addressSpace, registers, true); + } + _LIBUNWIND_ABORT("invalid compact unwind encoding"); +} + +template +int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( + compact_unwind_encoding_t compactEncoding, uint32_t functionStart, + A &addressSpace, Registers_x86 ®isters) { + uint32_t savedRegistersOffset = + EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_OFFSET); + uint32_t savedRegistersLocations = + EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_REGISTERS); + + uint32_t savedRegisters = registers.getEBP() - 4 * savedRegistersOffset; + for (int i = 0; i < 5; ++i) { + switch (savedRegistersLocations & 0x7) { + case UNWIND_X86_REG_NONE: + // no register saved in this slot + break; + case UNWIND_X86_REG_EBX: + registers.setEBX(addressSpace.get32(savedRegisters)); + break; + case UNWIND_X86_REG_ECX: + registers.setECX(addressSpace.get32(savedRegisters)); + break; + case UNWIND_X86_REG_EDX: + registers.setEDX(addressSpace.get32(savedRegisters)); + break; + case UNWIND_X86_REG_EDI: + registers.setEDI(addressSpace.get32(savedRegisters)); + break; + case UNWIND_X86_REG_ESI: + registers.setESI(addressSpace.get32(savedRegisters)); + break; + default: + (void)functionStart; + _LIBUNWIND_DEBUG_LOG("bad register for EBP frame, encoding=%08X for " + "function starting at 0x%X", + compactEncoding, functionStart); + _LIBUNWIND_ABORT("invalid compact unwind encoding"); + } + savedRegisters += 4; + savedRegistersLocations = (savedRegistersLocations >> 3); + } + frameUnwind(addressSpace, registers); + return UNW_STEP_SUCCESS; +} + +template +int CompactUnwinder_x86::stepWithCompactEncodingFrameless( + compact_unwind_encoding_t encoding, uint32_t functionStart, + A &addressSpace, Registers_x86 ®isters, bool indirectStackSize) { + uint32_t stackSizeEncoded = + EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); + uint32_t stackAdjust = + EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST); + uint32_t regCount = + EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = + EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); + uint32_t stackSize = stackSizeEncoded * 4; + if (indirectStackSize) { + // stack size is encoded in subl $xxx,%esp instruction + uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded); + stackSize = subl + 4 * stackAdjust; + } + // decompress permutation + uint32_t permunreg[6]; + switch (regCount) { + case 6: + permunreg[0] = permutation / 120; + permutation -= (permunreg[0] * 120); + permunreg[1] = permutation / 24; + permutation -= (permunreg[1] * 24); + permunreg[2] = permutation / 6; + permutation -= (permunreg[2] * 6); + permunreg[3] = permutation / 2; + permutation -= (permunreg[3] * 2); + permunreg[4] = permutation; + permunreg[5] = 0; + break; + case 5: + permunreg[0] = permutation / 120; + permutation -= (permunreg[0] * 120); + permunreg[1] = permutation / 24; + permutation -= (permunreg[1] * 24); + permunreg[2] = permutation / 6; + permutation -= (permunreg[2] * 6); + permunreg[3] = permutation / 2; + permutation -= (permunreg[3] * 2); + permunreg[4] = permutation; + break; + case 4: + permunreg[0] = permutation / 60; + permutation -= (permunreg[0] * 60); + permunreg[1] = permutation / 12; + permutation -= (permunreg[1] * 12); + permunreg[2] = permutation / 3; + permutation -= (permunreg[2] * 3); + permunreg[3] = permutation; + break; + case 3: + permunreg[0] = permutation / 20; + permutation -= (permunreg[0] * 20); + permunreg[1] = permutation / 4; + permutation -= (permunreg[1] * 4); + permunreg[2] = permutation; + break; + case 2: + permunreg[0] = permutation / 5; + permutation -= (permunreg[0] * 5); + permunreg[1] = permutation; + break; + case 1: + permunreg[0] = permutation; + break; + } + // re-number registers back to standard numbers + int registersSaved[6]; + bool used[7] = { false, false, false, false, false, false, false }; + for (uint32_t i = 0; i < regCount; ++i) { + uint32_t renum = 0; + for (int u = 1; u < 7; ++u) { + if (!used[u]) { + if (renum == permunreg[i]) { + registersSaved[i] = u; + used[u] = true; + break; + } + ++renum; + } + } + } + uint32_t savedRegisters = registers.getSP() + stackSize - 4 - 4 * regCount; + for (uint32_t i = 0; i < regCount; ++i) { + switch (registersSaved[i]) { + case UNWIND_X86_REG_EBX: + registers.setEBX(addressSpace.get32(savedRegisters)); + break; + case UNWIND_X86_REG_ECX: + registers.setECX(addressSpace.get32(savedRegisters)); + break; + case UNWIND_X86_REG_EDX: + registers.setEDX(addressSpace.get32(savedRegisters)); + break; + case UNWIND_X86_REG_EDI: + registers.setEDI(addressSpace.get32(savedRegisters)); + break; + case UNWIND_X86_REG_ESI: + registers.setESI(addressSpace.get32(savedRegisters)); + break; + case UNWIND_X86_REG_EBP: + registers.setEBP(addressSpace.get32(savedRegisters)); + break; + default: + _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " + "function starting at 0x%X", + encoding, functionStart); + _LIBUNWIND_ABORT("invalid compact unwind encoding"); + } + savedRegisters += 4; + } + framelessUnwind(addressSpace, savedRegisters, registers); + return UNW_STEP_SUCCESS; +} + + +template +void CompactUnwinder_x86::frameUnwind(A &addressSpace, + Registers_x86 ®isters) { + typename A::pint_t bp = registers.getEBP(); + // ebp points to old ebp + registers.setEBP(addressSpace.get32(bp)); + // old esp is ebp less saved ebp and return address + registers.setSP((uint32_t)bp + 8); + // pop return address into eip + registers.setIP(addressSpace.get32(bp + 4)); +} + +template +void CompactUnwinder_x86::framelessUnwind( + A &addressSpace, typename A::pint_t returnAddressLocation, + Registers_x86 ®isters) { + // return address is on stack after last saved register + registers.setIP(addressSpace.get32(returnAddressLocation)); + // old esp is before return address + registers.setSP((uint32_t)returnAddressLocation + 4); +} +#endif // _LIBUNWIND_TARGET_I386 + + +#if defined(_LIBUNWIND_TARGET_X86_64) +/// CompactUnwinder_x86_64 uses a compact unwind info to virtually "step" (aka +/// unwind) by modifying a Registers_x86_64 register set +template +class CompactUnwinder_x86_64 { +public: + + static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, + uint64_t functionStart, A &addressSpace, + Registers_x86_64 ®isters); + +private: + typename A::pint_t pint_t; + + static void frameUnwind(A &addressSpace, Registers_x86_64 ®isters); + static void framelessUnwind(A &addressSpace, uint64_t returnAddressLocation, + Registers_x86_64 ®isters); + static int + stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding, + uint64_t functionStart, A &addressSpace, + Registers_x86_64 ®isters); + static int stepWithCompactEncodingFrameless( + compact_unwind_encoding_t compactEncoding, uint64_t functionStart, + A &addressSpace, Registers_x86_64 ®isters, bool indirectStackSize); +}; + +template +int CompactUnwinder_x86_64::stepWithCompactEncoding( + compact_unwind_encoding_t compactEncoding, uint64_t functionStart, + A &addressSpace, Registers_x86_64 ®isters) { + switch (compactEncoding & UNWIND_X86_64_MODE_MASK) { + case UNWIND_X86_64_MODE_RBP_FRAME: + return stepWithCompactEncodingRBPFrame(compactEncoding, functionStart, + addressSpace, registers); + case UNWIND_X86_64_MODE_STACK_IMMD: + return stepWithCompactEncodingFrameless(compactEncoding, functionStart, + addressSpace, registers, false); + case UNWIND_X86_64_MODE_STACK_IND: + return stepWithCompactEncodingFrameless(compactEncoding, functionStart, + addressSpace, registers, true); + } + _LIBUNWIND_ABORT("invalid compact unwind encoding"); +} + +template +int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( + compact_unwind_encoding_t compactEncoding, uint64_t functionStart, + A &addressSpace, Registers_x86_64 ®isters) { + uint32_t savedRegistersOffset = + EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_OFFSET); + uint32_t savedRegistersLocations = + EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); + + uint64_t savedRegisters = registers.getRBP() - 8 * savedRegistersOffset; + for (int i = 0; i < 5; ++i) { + switch (savedRegistersLocations & 0x7) { + case UNWIND_X86_64_REG_NONE: + // no register saved in this slot + break; + case UNWIND_X86_64_REG_RBX: + registers.setRBX(addressSpace.get64(savedRegisters)); + break; + case UNWIND_X86_64_REG_R12: + registers.setR12(addressSpace.get64(savedRegisters)); + break; + case UNWIND_X86_64_REG_R13: + registers.setR13(addressSpace.get64(savedRegisters)); + break; + case UNWIND_X86_64_REG_R14: + registers.setR14(addressSpace.get64(savedRegisters)); + break; + case UNWIND_X86_64_REG_R15: + registers.setR15(addressSpace.get64(savedRegisters)); + break; + default: + (void)functionStart; + _LIBUNWIND_DEBUG_LOG("bad register for RBP frame, encoding=%08X for " + "function starting at 0x%llX", + compactEncoding, functionStart); + _LIBUNWIND_ABORT("invalid compact unwind encoding"); + } + savedRegisters += 8; + savedRegistersLocations = (savedRegistersLocations >> 3); + } + frameUnwind(addressSpace, registers); + return UNW_STEP_SUCCESS; +} + +template +int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( + compact_unwind_encoding_t encoding, uint64_t functionStart, A &addressSpace, + Registers_x86_64 ®isters, bool indirectStackSize) { + uint32_t stackSizeEncoded = + EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); + uint32_t stackAdjust = + EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); + uint32_t regCount = + EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = + EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); + uint32_t stackSize = stackSizeEncoded * 8; + if (indirectStackSize) { + // stack size is encoded in subl $xxx,%esp instruction + uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded); + stackSize = subl + 8 * stackAdjust; + } + // decompress permutation + uint32_t permunreg[6]; + switch (regCount) { + case 6: + permunreg[0] = permutation / 120; + permutation -= (permunreg[0] * 120); + permunreg[1] = permutation / 24; + permutation -= (permunreg[1] * 24); + permunreg[2] = permutation / 6; + permutation -= (permunreg[2] * 6); + permunreg[3] = permutation / 2; + permutation -= (permunreg[3] * 2); + permunreg[4] = permutation; + permunreg[5] = 0; + break; + case 5: + permunreg[0] = permutation / 120; + permutation -= (permunreg[0] * 120); + permunreg[1] = permutation / 24; + permutation -= (permunreg[1] * 24); + permunreg[2] = permutation / 6; + permutation -= (permunreg[2] * 6); + permunreg[3] = permutation / 2; + permutation -= (permunreg[3] * 2); + permunreg[4] = permutation; + break; + case 4: + permunreg[0] = permutation / 60; + permutation -= (permunreg[0] * 60); + permunreg[1] = permutation / 12; + permutation -= (permunreg[1] * 12); + permunreg[2] = permutation / 3; + permutation -= (permunreg[2] * 3); + permunreg[3] = permutation; + break; + case 3: + permunreg[0] = permutation / 20; + permutation -= (permunreg[0] * 20); + permunreg[1] = permutation / 4; + permutation -= (permunreg[1] * 4); + permunreg[2] = permutation; + break; + case 2: + permunreg[0] = permutation / 5; + permutation -= (permunreg[0] * 5); + permunreg[1] = permutation; + break; + case 1: + permunreg[0] = permutation; + break; + } + // re-number registers back to standard numbers + int registersSaved[6]; + bool used[7] = { false, false, false, false, false, false, false }; + for (uint32_t i = 0; i < regCount; ++i) { + uint32_t renum = 0; + for (int u = 1; u < 7; ++u) { + if (!used[u]) { + if (renum == permunreg[i]) { + registersSaved[i] = u; + used[u] = true; + break; + } + ++renum; + } + } + } + uint64_t savedRegisters = registers.getSP() + stackSize - 8 - 8 * regCount; + for (uint32_t i = 0; i < regCount; ++i) { + switch (registersSaved[i]) { + case UNWIND_X86_64_REG_RBX: + registers.setRBX(addressSpace.get64(savedRegisters)); + break; + case UNWIND_X86_64_REG_R12: + registers.setR12(addressSpace.get64(savedRegisters)); + break; + case UNWIND_X86_64_REG_R13: + registers.setR13(addressSpace.get64(savedRegisters)); + break; + case UNWIND_X86_64_REG_R14: + registers.setR14(addressSpace.get64(savedRegisters)); + break; + case UNWIND_X86_64_REG_R15: + registers.setR15(addressSpace.get64(savedRegisters)); + break; + case UNWIND_X86_64_REG_RBP: + registers.setRBP(addressSpace.get64(savedRegisters)); + break; + default: + _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " + "function starting at 0x%llX", + encoding, functionStart); + _LIBUNWIND_ABORT("invalid compact unwind encoding"); + } + savedRegisters += 8; + } + framelessUnwind(addressSpace, savedRegisters, registers); + return UNW_STEP_SUCCESS; +} + + +template +void CompactUnwinder_x86_64::frameUnwind(A &addressSpace, + Registers_x86_64 ®isters) { + uint64_t rbp = registers.getRBP(); + // ebp points to old ebp + registers.setRBP(addressSpace.get64(rbp)); + // old esp is ebp less saved ebp and return address + registers.setSP(rbp + 16); + // pop return address into eip + registers.setIP(addressSpace.get64(rbp + 8)); +} + +template +void CompactUnwinder_x86_64::framelessUnwind(A &addressSpace, + uint64_t returnAddressLocation, + Registers_x86_64 ®isters) { + // return address is on stack after last saved register + registers.setIP(addressSpace.get64(returnAddressLocation)); + // old esp is before return address + registers.setSP(returnAddressLocation + 8); +} +#endif // _LIBUNWIND_TARGET_X86_64 + + + +#if defined(_LIBUNWIND_TARGET_AARCH64) +/// CompactUnwinder_arm64 uses a compact unwind info to virtually "step" (aka +/// unwind) by modifying a Registers_arm64 register set +template +class CompactUnwinder_arm64 { +public: + + static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, + uint64_t functionStart, A &addressSpace, + Registers_arm64 ®isters); + +private: + typename A::pint_t pint_t; + + static int + stepWithCompactEncodingFrame(compact_unwind_encoding_t compactEncoding, + uint64_t functionStart, A &addressSpace, + Registers_arm64 ®isters); + static int stepWithCompactEncodingFrameless( + compact_unwind_encoding_t compactEncoding, uint64_t functionStart, + A &addressSpace, Registers_arm64 ®isters); +}; + +template +int CompactUnwinder_arm64::stepWithCompactEncoding( + compact_unwind_encoding_t compactEncoding, uint64_t functionStart, + A &addressSpace, Registers_arm64 ®isters) { + switch (compactEncoding & UNWIND_ARM64_MODE_MASK) { + case UNWIND_ARM64_MODE_FRAME: + return stepWithCompactEncodingFrame(compactEncoding, functionStart, + addressSpace, registers); + case UNWIND_ARM64_MODE_FRAMELESS: + return stepWithCompactEncodingFrameless(compactEncoding, functionStart, + addressSpace, registers); + } + _LIBUNWIND_ABORT("invalid compact unwind encoding"); +} + +template +int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( + compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, + Registers_arm64 ®isters) { + uint32_t stackSize = + 16 * EXTRACT_BITS(encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK); + + uint64_t savedRegisterLoc = registers.getSP() + stackSize; + + if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { + registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { + registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { + registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { + registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { + registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + + if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { + registers.setFloatRegister(UNW_ARM64_D8, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_ARM64_D9, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { + registers.setFloatRegister(UNW_ARM64_D10, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_ARM64_D11, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { + registers.setFloatRegister(UNW_ARM64_D12, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_ARM64_D13, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { + registers.setFloatRegister(UNW_ARM64_D14, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_ARM64_D15, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + + // subtract stack size off of sp + registers.setSP(savedRegisterLoc); + + // set pc to be value in lr + registers.setIP(registers.getRegister(UNW_ARM64_LR)); + + return UNW_STEP_SUCCESS; +} + +template +int CompactUnwinder_arm64::stepWithCompactEncodingFrame( + compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, + Registers_arm64 ®isters) { + uint64_t savedRegisterLoc = registers.getFP() - 8; + + if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { + registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { + registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { + registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { + registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { + registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + + if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { + registers.setFloatRegister(UNW_ARM64_D8, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_ARM64_D9, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { + registers.setFloatRegister(UNW_ARM64_D10, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_ARM64_D11, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { + registers.setFloatRegister(UNW_ARM64_D12, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_ARM64_D13, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { + registers.setFloatRegister(UNW_ARM64_D14, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_ARM64_D15, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + + uint64_t fp = registers.getFP(); + // fp points to old fp + registers.setFP(addressSpace.get64(fp)); + // old sp is fp less saved fp and lr + registers.setSP(fp + 16); + // pop return address into pc + registers.setIP(addressSpace.get64(fp + 8)); + + return UNW_STEP_SUCCESS; +} +#endif // _LIBUNWIND_TARGET_AARCH64 + + +} // namespace libunwind + +#endif // __COMPACT_UNWINDER_HPP__ Index: head/contrib/libunwind/src/DwarfInstructions.hpp =================================================================== --- head/contrib/libunwind/src/DwarfInstructions.hpp (nonexistent) +++ head/contrib/libunwind/src/DwarfInstructions.hpp (revision 345068) @@ -0,0 +1,795 @@ +//===-------------------------- DwarfInstructions.hpp ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Processor specific interpretation of DWARF unwind info. +// +//===----------------------------------------------------------------------===// + +#ifndef __DWARF_INSTRUCTIONS_HPP__ +#define __DWARF_INSTRUCTIONS_HPP__ + +#include +#include +#include + +#include "dwarf2.h" +#include "Registers.hpp" +#include "DwarfParser.hpp" +#include "config.h" + + +namespace libunwind { + + +/// DwarfInstructions maps abtract DWARF unwind instructions to a particular +/// architecture +template +class DwarfInstructions { +public: + typedef typename A::pint_t pint_t; + typedef typename A::sint_t sint_t; + + static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart, + R ®isters); + +private: + + enum { + DW_X86_64_RET_ADDR = 16 + }; + + enum { + DW_X86_RET_ADDR = 8 + }; + + typedef typename CFI_Parser::RegisterLocation RegisterLocation; + typedef typename CFI_Parser::PrologInfo PrologInfo; + typedef typename CFI_Parser::FDE_Info FDE_Info; + typedef typename CFI_Parser::CIE_Info CIE_Info; + + static pint_t evaluateExpression(pint_t expression, A &addressSpace, + const R ®isters, + pint_t initialStackValue); + static pint_t getSavedRegister(A &addressSpace, const R ®isters, + pint_t cfa, const RegisterLocation &savedReg); + static double getSavedFloatRegister(A &addressSpace, const R ®isters, + pint_t cfa, const RegisterLocation &savedReg); + static v128 getSavedVectorRegister(A &addressSpace, const R ®isters, + pint_t cfa, const RegisterLocation &savedReg); + + static pint_t getCFA(A &addressSpace, const PrologInfo &prolog, + const R ®isters) { + if (prolog.cfaRegister != 0) + return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) + + prolog.cfaRegisterOffset); + if (prolog.cfaExpression != 0) + return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, + registers, 0); + assert(0 && "getCFA(): unknown location"); + __builtin_unreachable(); + } +}; + + +template +typename A::pint_t DwarfInstructions::getSavedRegister( + A &addressSpace, const R ®isters, pint_t cfa, + const RegisterLocation &savedReg) { + switch (savedReg.location) { + case CFI_Parser::kRegisterInCFA: + return addressSpace.getRegister(cfa + (pint_t)savedReg.value); + + case CFI_Parser::kRegisterAtExpression: + return addressSpace.getRegister( + evaluateExpression((pint_t)savedReg.value, addressSpace, + registers, cfa)); + + case CFI_Parser::kRegisterIsExpression: + return evaluateExpression((pint_t)savedReg.value, addressSpace, + registers, cfa); + + case CFI_Parser::kRegisterInRegister: + return registers.getRegister((int)savedReg.value); + + case CFI_Parser::kRegisterUnused: + case CFI_Parser::kRegisterOffsetFromCFA: + // FIX ME + break; + } + _LIBUNWIND_ABORT("unsupported restore location for register"); +} + +template +double DwarfInstructions::getSavedFloatRegister( + A &addressSpace, const R ®isters, pint_t cfa, + const RegisterLocation &savedReg) { + switch (savedReg.location) { + case CFI_Parser::kRegisterInCFA: + return addressSpace.getDouble(cfa + (pint_t)savedReg.value); + + case CFI_Parser::kRegisterAtExpression: + return addressSpace.getDouble( + evaluateExpression((pint_t)savedReg.value, addressSpace, + registers, cfa)); + + case CFI_Parser::kRegisterIsExpression: + case CFI_Parser::kRegisterUnused: + case CFI_Parser::kRegisterOffsetFromCFA: + case CFI_Parser::kRegisterInRegister: + // FIX ME + break; + } + _LIBUNWIND_ABORT("unsupported restore location for float register"); +} + +template +v128 DwarfInstructions::getSavedVectorRegister( + A &addressSpace, const R ®isters, pint_t cfa, + const RegisterLocation &savedReg) { + switch (savedReg.location) { + case CFI_Parser::kRegisterInCFA: + return addressSpace.getVector(cfa + (pint_t)savedReg.value); + + case CFI_Parser::kRegisterAtExpression: + return addressSpace.getVector( + evaluateExpression((pint_t)savedReg.value, addressSpace, + registers, cfa)); + + case CFI_Parser::kRegisterIsExpression: + case CFI_Parser::kRegisterUnused: + case CFI_Parser::kRegisterOffsetFromCFA: + case CFI_Parser::kRegisterInRegister: + // FIX ME + break; + } + _LIBUNWIND_ABORT("unsupported restore location for vector register"); +} + +template +int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, + pint_t fdeStart, R ®isters) { + FDE_Info fdeInfo; + CIE_Info cieInfo; + if (CFI_Parser::decodeFDE(addressSpace, fdeStart, &fdeInfo, + &cieInfo) == NULL) { + PrologInfo prolog; + if (CFI_Parser::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, + R::getArch(), &prolog)) { + // get pointer to cfa (architecture specific) + pint_t cfa = getCFA(addressSpace, prolog, registers); + + // restore registers that DWARF says were saved + R newRegisters = registers; + pint_t returnAddress = 0; + const int lastReg = R::lastDwarfRegNum(); + assert(static_cast(CFI_Parser::kMaxRegisterNumber) >= lastReg && + "register range too large"); + assert(lastReg >= (int)cieInfo.returnAddressRegister && + "register range does not contain return address register"); + for (int i = 0; i <= lastReg; ++i) { + if (prolog.savedRegisters[i].location != + CFI_Parser::kRegisterUnused) { + if (registers.validFloatRegister(i)) + newRegisters.setFloatRegister( + i, getSavedFloatRegister(addressSpace, registers, cfa, + prolog.savedRegisters[i])); + else if (registers.validVectorRegister(i)) + newRegisters.setVectorRegister( + i, getSavedVectorRegister(addressSpace, registers, cfa, + prolog.savedRegisters[i])); + else if (i == (int)cieInfo.returnAddressRegister) + returnAddress = getSavedRegister(addressSpace, registers, cfa, + prolog.savedRegisters[i]); + else if (registers.validRegister(i)) + newRegisters.setRegister( + i, getSavedRegister(addressSpace, registers, cfa, + prolog.savedRegisters[i])); + else + return UNW_EBADREG; + } + } + + // By definition, the CFA is the stack pointer at the call site, so + // restoring SP means setting it to CFA. + newRegisters.setSP(cfa); + +#if defined(_LIBUNWIND_TARGET_AARCH64) + // If the target is aarch64 then the return address may have been signed + // using the v8.3 pointer authentication extensions. The original + // return address needs to be authenticated before the return address is + // restored. autia1716 is used instead of autia as autia1716 assembles + // to a NOP on pre-v8.3a architectures. + if ((R::getArch() == REGISTERS_ARM64) && + prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) { +#if !defined(_LIBUNWIND_IS_NATIVE_ONLY) + return UNW_ECROSSRASIGNING; +#else + register unsigned long long x17 __asm("x17") = returnAddress; + register unsigned long long x16 __asm("x16") = cfa; + + // These are the autia1716/autib1716 instructions. The hint instructions + // are used here as gcc does not assemble autia1716/autib1716 for pre + // armv8.3a targets. + if (cieInfo.addressesSignedWithBKey) + asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716 + else + asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716 + returnAddress = x17; +#endif + } +#endif + +#if defined(_LIBUNWIND_TARGET_SPARC) + if (R::getArch() == REGISTERS_SPARC) { + // Skip call site instruction and delay slot + returnAddress += 8; + // Skip unimp instruction if function returns a struct + if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0) + returnAddress += 4; + } +#endif + + // Return address is address after call site instruction, so setting IP to + // that does simualates a return. + newRegisters.setIP(returnAddress); + + // Simulate the step by replacing the register set with the new ones. + registers = newRegisters; + + return UNW_STEP_SUCCESS; + } + } + return UNW_EBADFRAME; +} + +template +typename A::pint_t +DwarfInstructions::evaluateExpression(pint_t expression, A &addressSpace, + const R ®isters, + pint_t initialStackValue) { + const bool log = false; + pint_t p = expression; + pint_t expressionEnd = expression + 20; // temp, until len read + pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd); + expressionEnd = p + length; + if (log) + fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n", + (uint64_t)length); + pint_t stack[100]; + pint_t *sp = stack; + *(++sp) = initialStackValue; + + while (p < expressionEnd) { + if (log) { + for (pint_t *t = sp; t > stack; --t) { + fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t)); + } + } + uint8_t opcode = addressSpace.get8(p++); + sint_t svalue, svalue2; + pint_t value; + uint32_t reg; + switch (opcode) { + case DW_OP_addr: + // push immediate address sized value + value = addressSpace.getP(p); + p += sizeof(pint_t); + *(++sp) = value; + if (log) + fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); + break; + + case DW_OP_deref: + // pop stack, dereference, push result + value = *sp--; + *(++sp) = addressSpace.getP(value); + if (log) + fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value); + break; + + case DW_OP_const1u: + // push immediate 1 byte value + value = addressSpace.get8(p); + p += 1; + *(++sp) = value; + if (log) + fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); + break; + + case DW_OP_const1s: + // push immediate 1 byte signed value + svalue = (int8_t) addressSpace.get8(p); + p += 1; + *(++sp) = (pint_t)svalue; + if (log) + fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); + break; + + case DW_OP_const2u: + // push immediate 2 byte value + value = addressSpace.get16(p); + p += 2; + *(++sp) = value; + if (log) + fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); + break; + + case DW_OP_const2s: + // push immediate 2 byte signed value + svalue = (int16_t) addressSpace.get16(p); + p += 2; + *(++sp) = (pint_t)svalue; + if (log) + fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); + break; + + case DW_OP_const4u: + // push immediate 4 byte value + value = addressSpace.get32(p); + p += 4; + *(++sp) = value; + if (log) + fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); + break; + + case DW_OP_const4s: + // push immediate 4 byte signed value + svalue = (int32_t)addressSpace.get32(p); + p += 4; + *(++sp) = (pint_t)svalue; + if (log) + fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); + break; + + case DW_OP_const8u: + // push immediate 8 byte value + value = (pint_t)addressSpace.get64(p); + p += 8; + *(++sp) = value; + if (log) + fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); + break; + + case DW_OP_const8s: + // push immediate 8 byte signed value + value = (pint_t)addressSpace.get64(p); + p += 8; + *(++sp) = value; + if (log) + fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); + break; + + case DW_OP_constu: + // push immediate ULEB128 value + value = (pint_t)addressSpace.getULEB128(p, expressionEnd); + *(++sp) = value; + if (log) + fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); + break; + + case DW_OP_consts: + // push immediate SLEB128 value + svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); + *(++sp) = (pint_t)svalue; + if (log) + fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); + break; + + case DW_OP_dup: + // push top of stack + value = *sp; + *(++sp) = value; + if (log) + fprintf(stderr, "duplicate top of stack\n"); + break; + + case DW_OP_drop: + // pop + --sp; + if (log) + fprintf(stderr, "pop top of stack\n"); + break; + + case DW_OP_over: + // dup second + value = sp[-1]; + *(++sp) = value; + if (log) + fprintf(stderr, "duplicate second in stack\n"); + break; + + case DW_OP_pick: + // pick from + reg = addressSpace.get8(p); + p += 1; + value = sp[-reg]; + *(++sp) = value; + if (log) + fprintf(stderr, "duplicate %d in stack\n", reg); + break; + + case DW_OP_swap: + // swap top two + value = sp[0]; + sp[0] = sp[-1]; + sp[-1] = value; + if (log) + fprintf(stderr, "swap top of stack\n"); + break; + + case DW_OP_rot: + // rotate top three + value = sp[0]; + sp[0] = sp[-1]; + sp[-1] = sp[-2]; + sp[-2] = value; + if (log) + fprintf(stderr, "rotate top three of stack\n"); + break; + + case DW_OP_xderef: + // pop stack, dereference, push result + value = *sp--; + *sp = *((pint_t*)value); + if (log) + fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value); + break; + + case DW_OP_abs: + svalue = (sint_t)*sp; + if (svalue < 0) + *sp = (pint_t)(-svalue); + if (log) + fprintf(stderr, "abs\n"); + break; + + case DW_OP_and: + value = *sp--; + *sp &= value; + if (log) + fprintf(stderr, "and\n"); + break; + + case DW_OP_div: + svalue = (sint_t)(*sp--); + svalue2 = (sint_t)*sp; + *sp = (pint_t)(svalue2 / svalue); + if (log) + fprintf(stderr, "div\n"); + break; + + case DW_OP_minus: + value = *sp--; + *sp = *sp - value; + if (log) + fprintf(stderr, "minus\n"); + break; + + case DW_OP_mod: + svalue = (sint_t)(*sp--); + svalue2 = (sint_t)*sp; + *sp = (pint_t)(svalue2 % svalue); + if (log) + fprintf(stderr, "module\n"); + break; + + case DW_OP_mul: + svalue = (sint_t)(*sp--); + svalue2 = (sint_t)*sp; + *sp = (pint_t)(svalue2 * svalue); + if (log) + fprintf(stderr, "mul\n"); + break; + + case DW_OP_neg: + *sp = 0 - *sp; + if (log) + fprintf(stderr, "neg\n"); + break; + + case DW_OP_not: + svalue = (sint_t)(*sp); + *sp = (pint_t)(~svalue); + if (log) + fprintf(stderr, "not\n"); + break; + + case DW_OP_or: + value = *sp--; + *sp |= value; + if (log) + fprintf(stderr, "or\n"); + break; + + case DW_OP_plus: + value = *sp--; + *sp += value; + if (log) + fprintf(stderr, "plus\n"); + break; + + case DW_OP_plus_uconst: + // pop stack, add uelb128 constant, push result + *sp += static_cast(addressSpace.getULEB128(p, expressionEnd)); + if (log) + fprintf(stderr, "add constant\n"); + break; + + case DW_OP_shl: + value = *sp--; + *sp = *sp << value; + if (log) + fprintf(stderr, "shift left\n"); + break; + + case DW_OP_shr: + value = *sp--; + *sp = *sp >> value; + if (log) + fprintf(stderr, "shift left\n"); + break; + + case DW_OP_shra: + value = *sp--; + svalue = (sint_t)*sp; + *sp = (pint_t)(svalue >> value); + if (log) + fprintf(stderr, "shift left arithmetric\n"); + break; + + case DW_OP_xor: + value = *sp--; + *sp ^= value; + if (log) + fprintf(stderr, "xor\n"); + break; + + case DW_OP_skip: + svalue = (int16_t) addressSpace.get16(p); + p += 2; + p = (pint_t)((sint_t)p + svalue); + if (log) + fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue); + break; + + case DW_OP_bra: + svalue = (int16_t) addressSpace.get16(p); + p += 2; + if (*sp--) + p = (pint_t)((sint_t)p + svalue); + if (log) + fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue); + break; + + case DW_OP_eq: + value = *sp--; + *sp = (*sp == value); + if (log) + fprintf(stderr, "eq\n"); + break; + + case DW_OP_ge: + value = *sp--; + *sp = (*sp >= value); + if (log) + fprintf(stderr, "ge\n"); + break; + + case DW_OP_gt: + value = *sp--; + *sp = (*sp > value); + if (log) + fprintf(stderr, "gt\n"); + break; + + case DW_OP_le: + value = *sp--; + *sp = (*sp <= value); + if (log) + fprintf(stderr, "le\n"); + break; + + case DW_OP_lt: + value = *sp--; + *sp = (*sp < value); + if (log) + fprintf(stderr, "lt\n"); + break; + + case DW_OP_ne: + value = *sp--; + *sp = (*sp != value); + if (log) + fprintf(stderr, "ne\n"); + break; + + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + value = static_cast(opcode - DW_OP_lit0); + *(++sp) = value; + if (log) + fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value); + break; + + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + reg = static_cast(opcode - DW_OP_reg0); + *(++sp) = registers.getRegister((int)reg); + if (log) + fprintf(stderr, "push reg %d\n", reg); + break; + + case DW_OP_regx: + reg = static_cast(addressSpace.getULEB128(p, expressionEnd)); + *(++sp) = registers.getRegister((int)reg); + if (log) + fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); + break; + + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + reg = static_cast(opcode - DW_OP_breg0); + svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); + svalue += static_cast(registers.getRegister((int)reg)); + *(++sp) = (pint_t)(svalue); + if (log) + fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); + break; + + case DW_OP_bregx: + reg = static_cast(addressSpace.getULEB128(p, expressionEnd)); + svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); + svalue += static_cast(registers.getRegister((int)reg)); + *(++sp) = (pint_t)(svalue); + if (log) + fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); + break; + + case DW_OP_fbreg: + _LIBUNWIND_ABORT("DW_OP_fbreg not implemented"); + break; + + case DW_OP_piece: + _LIBUNWIND_ABORT("DW_OP_piece not implemented"); + break; + + case DW_OP_deref_size: + // pop stack, dereference, push result + value = *sp--; + switch (addressSpace.get8(p++)) { + case 1: + value = addressSpace.get8(value); + break; + case 2: + value = addressSpace.get16(value); + break; + case 4: + value = addressSpace.get32(value); + break; + case 8: + value = (pint_t)addressSpace.get64(value); + break; + default: + _LIBUNWIND_ABORT("DW_OP_deref_size with bad size"); + } + *(++sp) = value; + if (log) + fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value); + break; + + case DW_OP_xderef_size: + case DW_OP_nop: + case DW_OP_push_object_addres: + case DW_OP_call2: + case DW_OP_call4: + case DW_OP_call_ref: + default: + _LIBUNWIND_ABORT("DWARF opcode not implemented"); + } + + } + if (log) + fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp); + return *sp; +} + + + +} // namespace libunwind + +#endif // __DWARF_INSTRUCTIONS_HPP__ Index: head/contrib/libunwind/src/DwarfParser.hpp =================================================================== --- head/contrib/libunwind/src/DwarfParser.hpp (nonexistent) +++ head/contrib/libunwind/src/DwarfParser.hpp (revision 345068) @@ -0,0 +1,766 @@ +//===--------------------------- DwarfParser.hpp --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Parses DWARF CFIs (FDEs and CIEs). +// +//===----------------------------------------------------------------------===// + +#ifndef __DWARF_PARSER_HPP__ +#define __DWARF_PARSER_HPP__ + +#include +#include +#include +#include + +#include "libunwind.h" +#include "dwarf2.h" +#include "Registers.hpp" + +#include "config.h" + +namespace libunwind { + +/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records. +/// See DWARF Spec for details: +/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html +/// +template +class CFI_Parser { +public: + typedef typename A::pint_t pint_t; + + /// Information encoded in a CIE (Common Information Entry) + struct CIE_Info { + pint_t cieStart; + pint_t cieLength; + pint_t cieInstructions; + uint8_t pointerEncoding; + uint8_t lsdaEncoding; + uint8_t personalityEncoding; + uint8_t personalityOffsetInCIE; + pint_t personality; + uint32_t codeAlignFactor; + int dataAlignFactor; + bool isSignalFrame; + bool fdesHaveAugmentationData; + uint8_t returnAddressRegister; +#if defined(_LIBUNWIND_TARGET_AARCH64) + bool addressesSignedWithBKey; +#endif + }; + + /// Information about an FDE (Frame Description Entry) + struct FDE_Info { + pint_t fdeStart; + pint_t fdeLength; + pint_t fdeInstructions; + pint_t pcStart; + pint_t pcEnd; + pint_t lsda; + }; + + enum { + kMaxRegisterNumber = _LIBUNWIND_HIGHEST_DWARF_REGISTER + }; + enum RegisterSavedWhere { + kRegisterUnused, + kRegisterInCFA, + kRegisterOffsetFromCFA, + kRegisterInRegister, + kRegisterAtExpression, + kRegisterIsExpression + }; + struct RegisterLocation { + RegisterSavedWhere location; + int64_t value; + }; + /// Information about a frame layout and registers saved determined + /// by "running" the DWARF FDE "instructions" + struct PrologInfo { + uint32_t cfaRegister; + int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset + int64_t cfaExpression; // CFA = expression + uint32_t spExtraArgSize; + uint32_t codeOffsetAtStackDecrement; + bool registersInOtherRegisters; + bool sameValueUsed; + RegisterLocation savedRegisters[kMaxRegisterNumber + 1]; + }; + + struct PrologInfoStackEntry { + PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i) + : next(n), info(i) {} + PrologInfoStackEntry *next; + PrologInfo info; + }; + + static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, + uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, + CIE_Info *cieInfo); + static const char *decodeFDE(A &addressSpace, pint_t fdeStart, + FDE_Info *fdeInfo, CIE_Info *cieInfo); + static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, + const CIE_Info &cieInfo, pint_t upToPC, + int arch, PrologInfo *results); + + static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); + +private: + static bool parseInstructions(A &addressSpace, pint_t instructions, + pint_t instructionsEnd, const CIE_Info &cieInfo, + pint_t pcoffset, + PrologInfoStackEntry *&rememberStack, int arch, + PrologInfo *results); +}; + +/// Parse a FDE into a CIE_Info and an FDE_Info +template +const char *CFI_Parser::decodeFDE(A &addressSpace, pint_t fdeStart, + FDE_Info *fdeInfo, CIE_Info *cieInfo) { + pint_t p = fdeStart; + pint_t cfiLength = (pint_t)addressSpace.get32(p); + p += 4; + if (cfiLength == 0xffffffff) { + // 0xffffffff means length is really next 8 bytes + cfiLength = (pint_t)addressSpace.get64(p); + p += 8; + } + if (cfiLength == 0) + return "FDE has zero length"; // end marker + uint32_t ciePointer = addressSpace.get32(p); + if (ciePointer == 0) + return "FDE is really a CIE"; // this is a CIE not an FDE + pint_t nextCFI = p + cfiLength; + pint_t cieStart = p - ciePointer; + const char *err = parseCIE(addressSpace, cieStart, cieInfo); + if (err != NULL) + return err; + p += 4; + // Parse pc begin and range. + pint_t pcStart = + addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding); + pint_t pcRange = + addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F); + // Parse rest of info. + fdeInfo->lsda = 0; + // Check for augmentation length. + if (cieInfo->fdesHaveAugmentationData) { + pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI); + pint_t endOfAug = p + augLen; + if (cieInfo->lsdaEncoding != DW_EH_PE_omit) { + // Peek at value (without indirection). Zero means no LSDA. + pint_t lsdaStart = p; + if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != + 0) { + // Reset pointer and re-parse LSDA address. + p = lsdaStart; + fdeInfo->lsda = + addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding); + } + } + p = endOfAug; + } + fdeInfo->fdeStart = fdeStart; + fdeInfo->fdeLength = nextCFI - fdeStart; + fdeInfo->fdeInstructions = p; + fdeInfo->pcStart = pcStart; + fdeInfo->pcEnd = pcStart + pcRange; + return NULL; // success +} + +/// Scan an eh_frame section to find an FDE for a pc +template +bool CFI_Parser::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, + uint32_t sectionLength, pint_t fdeHint, + FDE_Info *fdeInfo, CIE_Info *cieInfo) { + //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); + pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart; + const pint_t ehSectionEnd = p + sectionLength; + while (p < ehSectionEnd) { + pint_t currentCFI = p; + //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p); + pint_t cfiLength = addressSpace.get32(p); + p += 4; + if (cfiLength == 0xffffffff) { + // 0xffffffff means length is really next 8 bytes + cfiLength = (pint_t)addressSpace.get64(p); + p += 8; + } + if (cfiLength == 0) + return false; // end marker + uint32_t id = addressSpace.get32(p); + if (id == 0) { + // Skip over CIEs. + p += cfiLength; + } else { + // Process FDE to see if it covers pc. + pint_t nextCFI = p + cfiLength; + uint32_t ciePointer = addressSpace.get32(p); + pint_t cieStart = p - ciePointer; + // Validate pointer to CIE is within section. + if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) { + if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) { + p += 4; + // Parse pc begin and range. + pint_t pcStart = + addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding); + pint_t pcRange = addressSpace.getEncodedP( + p, nextCFI, cieInfo->pointerEncoding & 0x0F); + // Test if pc is within the function this FDE covers. + if ((pcStart < pc) && (pc <= pcStart + pcRange)) { + // parse rest of info + fdeInfo->lsda = 0; + // check for augmentation length + if (cieInfo->fdesHaveAugmentationData) { + pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI); + pint_t endOfAug = p + augLen; + if (cieInfo->lsdaEncoding != DW_EH_PE_omit) { + // Peek at value (without indirection). Zero means no LSDA. + pint_t lsdaStart = p; + if (addressSpace.getEncodedP( + p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) { + // Reset pointer and re-parse LSDA address. + p = lsdaStart; + fdeInfo->lsda = addressSpace + .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding); + } + } + p = endOfAug; + } + fdeInfo->fdeStart = currentCFI; + fdeInfo->fdeLength = nextCFI - currentCFI; + fdeInfo->fdeInstructions = p; + fdeInfo->pcStart = pcStart; + fdeInfo->pcEnd = pcStart + pcRange; + return true; + } else { + // pc is not in begin/range, skip this FDE + } + } else { + // Malformed CIE, now augmentation describing pc range encoding. + } + } else { + // malformed FDE. CIE is bad + } + p = nextCFI; + } + } + return false; +} + +/// Extract info from a CIE +template +const char *CFI_Parser::parseCIE(A &addressSpace, pint_t cie, + CIE_Info *cieInfo) { + cieInfo->pointerEncoding = 0; + cieInfo->lsdaEncoding = DW_EH_PE_omit; + cieInfo->personalityEncoding = 0; + cieInfo->personalityOffsetInCIE = 0; + cieInfo->personality = 0; + cieInfo->codeAlignFactor = 0; + cieInfo->dataAlignFactor = 0; + cieInfo->isSignalFrame = false; + cieInfo->fdesHaveAugmentationData = false; +#if defined(_LIBUNWIND_TARGET_AARCH64) + cieInfo->addressesSignedWithBKey = false; +#endif + cieInfo->cieStart = cie; + pint_t p = cie; + pint_t cieLength = (pint_t)addressSpace.get32(p); + p += 4; + pint_t cieContentEnd = p + cieLength; + if (cieLength == 0xffffffff) { + // 0xffffffff means length is really next 8 bytes + cieLength = (pint_t)addressSpace.get64(p); + p += 8; + cieContentEnd = p + cieLength; + } + if (cieLength == 0) + return NULL; + // CIE ID is always 0 + if (addressSpace.get32(p) != 0) + return "CIE ID is not zero"; + p += 4; + // Version is always 1 or 3 + uint8_t version = addressSpace.get8(p); + if ((version != 1) && (version != 3)) + return "CIE version is not 1 or 3"; + ++p; + // save start of augmentation string and find end + pint_t strStart = p; + while (addressSpace.get8(p) != 0) + ++p; + ++p; + // parse code aligment factor + cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd); + // parse data alignment factor + cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd); + // parse return address register + uint64_t raReg = addressSpace.getULEB128(p, cieContentEnd); + assert(raReg < 255 && "return address register too large"); + cieInfo->returnAddressRegister = (uint8_t)raReg; + // parse augmentation data based on augmentation string + const char *result = NULL; + if (addressSpace.get8(strStart) == 'z') { + // parse augmentation data length + addressSpace.getULEB128(p, cieContentEnd); + for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) { + switch (addressSpace.get8(s)) { + case 'z': + cieInfo->fdesHaveAugmentationData = true; + break; + case 'P': + cieInfo->personalityEncoding = addressSpace.get8(p); + ++p; + cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie); + cieInfo->personality = addressSpace + .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding); + break; + case 'L': + cieInfo->lsdaEncoding = addressSpace.get8(p); + ++p; + break; + case 'R': + cieInfo->pointerEncoding = addressSpace.get8(p); + ++p; + break; + case 'S': + cieInfo->isSignalFrame = true; + break; +#if defined(_LIBUNWIND_TARGET_AARCH64) + case 'B': + cieInfo->addressesSignedWithBKey = true; + break; +#endif + default: + // ignore unknown letters + break; + } + } + } + cieInfo->cieLength = cieContentEnd - cieInfo->cieStart; + cieInfo->cieInstructions = p; + return result; +} + + +/// "run" the DWARF instructions and create the abstact PrologInfo for an FDE +template +bool CFI_Parser::parseFDEInstructions(A &addressSpace, + const FDE_Info &fdeInfo, + const CIE_Info &cieInfo, pint_t upToPC, + int arch, PrologInfo *results) { + // clear results + memset(results, '\0', sizeof(PrologInfo)); + PrologInfoStackEntry *rememberStack = NULL; + + // parse CIE then FDE instructions + return parseInstructions(addressSpace, cieInfo.cieInstructions, + cieInfo.cieStart + cieInfo.cieLength, cieInfo, + (pint_t)(-1), rememberStack, arch, results) && + parseInstructions(addressSpace, fdeInfo.fdeInstructions, + fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, + upToPC - fdeInfo.pcStart, rememberStack, arch, + results); +} + +/// "run" the DWARF instructions +template +bool CFI_Parser::parseInstructions(A &addressSpace, pint_t instructions, + pint_t instructionsEnd, + const CIE_Info &cieInfo, pint_t pcoffset, + PrologInfoStackEntry *&rememberStack, + int arch, PrologInfo *results) { + pint_t p = instructions; + pint_t codeOffset = 0; + PrologInfo initialState = *results; + + _LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n", + static_cast(instructionsEnd)); + + // see DWARF Spec, section 6.4.2 for details on unwind opcodes + while ((p < instructionsEnd) && (codeOffset < pcoffset)) { + uint64_t reg; + uint64_t reg2; + int64_t offset; + uint64_t length; + uint8_t opcode = addressSpace.get8(p); + uint8_t operand; +#if !defined(_LIBUNWIND_NO_HEAP) + PrologInfoStackEntry *entry; +#endif + ++p; + switch (opcode) { + case DW_CFA_nop: + _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n"); + break; + case DW_CFA_set_loc: + codeOffset = + addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding); + _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n"); + break; + case DW_CFA_advance_loc1: + codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor); + p += 1; + _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n", + static_cast(codeOffset)); + break; + case DW_CFA_advance_loc2: + codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor); + p += 2; + _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n", + static_cast(codeOffset)); + break; + case DW_CFA_advance_loc4: + codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor); + p += 4; + _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n", + static_cast(codeOffset)); + break; + case DW_CFA_offset_extended: + reg = addressSpace.getULEB128(p, instructionsEnd); + offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) + * cieInfo.dataAlignFactor; + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG0( + "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); + return false; + } + results->savedRegisters[reg].location = kRegisterInCFA; + results->savedRegisters[reg].value = offset; + _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", " + "offset=%" PRId64 ")\n", + reg, offset); + break; + case DW_CFA_restore_extended: + reg = addressSpace.getULEB128(p, instructionsEnd); + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG0( + "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); + return false; + } + results->savedRegisters[reg] = initialState.savedRegisters[reg]; + _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg); + break; + case DW_CFA_undefined: + reg = addressSpace.getULEB128(p, instructionsEnd); + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG0( + "malformed DW_CFA_undefined DWARF unwind, reg too big"); + return false; + } + results->savedRegisters[reg].location = kRegisterUnused; + _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); + break; + case DW_CFA_same_value: + reg = addressSpace.getULEB128(p, instructionsEnd); + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG0( + "malformed DW_CFA_same_value DWARF unwind, reg too big"); + return false; + } + // DW_CFA_same_value unsupported + // "same value" means register was stored in frame, but its current + // value has not changed, so no need to restore from frame. + // We model this as if the register was never saved. + results->savedRegisters[reg].location = kRegisterUnused; + // set flag to disable conversion to compact unwind + results->sameValueUsed = true; + _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); + break; + case DW_CFA_register: + reg = addressSpace.getULEB128(p, instructionsEnd); + reg2 = addressSpace.getULEB128(p, instructionsEnd); + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG0( + "malformed DW_CFA_register DWARF unwind, reg too big"); + return false; + } + if (reg2 > kMaxRegisterNumber) { + _LIBUNWIND_LOG0( + "malformed DW_CFA_register DWARF unwind, reg2 too big"); + return false; + } + results->savedRegisters[reg].location = kRegisterInRegister; + results->savedRegisters[reg].value = (int64_t)reg2; + // set flag to disable conversion to compact unwind + results->registersInOtherRegisters = true; + _LIBUNWIND_TRACE_DWARF( + "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2); + break; +#if !defined(_LIBUNWIND_NO_HEAP) + case DW_CFA_remember_state: + // avoid operator new, because that would be an upward dependency + entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry)); + if (entry != NULL) { + entry->next = rememberStack; + entry->info = *results; + rememberStack = entry; + } else { + return false; + } + _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n"); + break; + case DW_CFA_restore_state: + if (rememberStack != NULL) { + PrologInfoStackEntry *top = rememberStack; + *results = top->info; + rememberStack = top->next; + free((char *)top); + } else { + return false; + } + _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n"); + break; +#endif + case DW_CFA_def_cfa: + reg = addressSpace.getULEB128(p, instructionsEnd); + offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd); + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big"); + return false; + } + results->cfaRegister = (uint32_t)reg; + results->cfaRegisterOffset = (int32_t)offset; + _LIBUNWIND_TRACE_DWARF( + "DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n", reg, offset); + break; + case DW_CFA_def_cfa_register: + reg = addressSpace.getULEB128(p, instructionsEnd); + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG0( + "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big"); + return false; + } + results->cfaRegister = (uint32_t)reg; + _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg); + break; + case DW_CFA_def_cfa_offset: + results->cfaRegisterOffset = (int32_t) + addressSpace.getULEB128(p, instructionsEnd); + results->codeOffsetAtStackDecrement = (uint32_t)codeOffset; + _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n", + results->cfaRegisterOffset); + break; + case DW_CFA_def_cfa_expression: + results->cfaRegister = 0; + results->cfaExpression = (int64_t)p; + length = addressSpace.getULEB128(p, instructionsEnd); + assert(length < static_cast(~0) && "pointer overflow"); + p += static_cast(length); + _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64 + ", length=%" PRIu64 ")\n", + results->cfaExpression, length); + break; + case DW_CFA_expression: + reg = addressSpace.getULEB128(p, instructionsEnd); + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG0( + "malformed DW_CFA_expression DWARF unwind, reg too big"); + return false; + } + results->savedRegisters[reg].location = kRegisterAtExpression; + results->savedRegisters[reg].value = (int64_t)p; + length = addressSpace.getULEB128(p, instructionsEnd); + assert(length < static_cast(~0) && "pointer overflow"); + p += static_cast(length); + _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", " + "expression=0x%" PRIx64 ", " + "length=%" PRIu64 ")\n", + reg, results->savedRegisters[reg].value, length); + break; + case DW_CFA_offset_extended_sf: + reg = addressSpace.getULEB128(p, instructionsEnd); + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG0( + "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big"); + return false; + } + offset = + addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; + results->savedRegisters[reg].location = kRegisterInCFA; + results->savedRegisters[reg].value = offset; + _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", " + "offset=%" PRId64 ")\n", + reg, offset); + break; + case DW_CFA_def_cfa_sf: + reg = addressSpace.getULEB128(p, instructionsEnd); + offset = + addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG0( + "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big"); + return false; + } + results->cfaRegister = (uint32_t)reg; + results->cfaRegisterOffset = (int32_t)offset; + _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", " + "offset=%" PRId64 ")\n", + reg, offset); + break; + case DW_CFA_def_cfa_offset_sf: + results->cfaRegisterOffset = (int32_t) + (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor); + results->codeOffsetAtStackDecrement = (uint32_t)codeOffset; + _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n", + results->cfaRegisterOffset); + break; + case DW_CFA_val_offset: + reg = addressSpace.getULEB128(p, instructionsEnd); + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG( + "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64 + ") out of range\n", + reg); + return false; + } + offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) + * cieInfo.dataAlignFactor; + results->savedRegisters[reg].location = kRegisterOffsetFromCFA; + results->savedRegisters[reg].value = offset; + _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", " + "offset=%" PRId64 "\n", + reg, offset); + break; + case DW_CFA_val_offset_sf: + reg = addressSpace.getULEB128(p, instructionsEnd); + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG0( + "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big"); + return false; + } + offset = + addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; + results->savedRegisters[reg].location = kRegisterOffsetFromCFA; + results->savedRegisters[reg].value = offset; + _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", " + "offset=%" PRId64 "\n", + reg, offset); + break; + case DW_CFA_val_expression: + reg = addressSpace.getULEB128(p, instructionsEnd); + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG0( + "malformed DW_CFA_val_expression DWARF unwind, reg too big"); + return false; + } + results->savedRegisters[reg].location = kRegisterIsExpression; + results->savedRegisters[reg].value = (int64_t)p; + length = addressSpace.getULEB128(p, instructionsEnd); + assert(length < static_cast(~0) && "pointer overflow"); + p += static_cast(length); + _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", " + "expression=0x%" PRIx64 ", length=%" PRIu64 ")\n", + reg, results->savedRegisters[reg].value, length); + break; + case DW_CFA_GNU_args_size: + length = addressSpace.getULEB128(p, instructionsEnd); + results->spExtraArgSize = (uint32_t)length; + _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length); + break; + case DW_CFA_GNU_negative_offset_extended: + reg = addressSpace.getULEB128(p, instructionsEnd); + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF " + "unwind, reg too big"); + return false; + } + offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) + * cieInfo.dataAlignFactor; + results->savedRegisters[reg].location = kRegisterInCFA; + results->savedRegisters[reg].value = -offset; + _LIBUNWIND_TRACE_DWARF( + "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); + break; + +#if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) + // The same constant is used to represent different instructions on + // AArch64 (negate_ra_state) and SPARC (window_save). + static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save, + "uses the same constant"); + case DW_CFA_AARCH64_negate_ra_state: + switch (arch) { +#if defined(_LIBUNWIND_TARGET_AARCH64) + case REGISTERS_ARM64: + results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^= 0x1; + _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); + break; +#endif +#if defined(_LIBUNWIND_TARGET_SPARC) + // case DW_CFA_GNU_window_save: + case REGISTERS_SPARC: + _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n"); + for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) { + results->savedRegisters[reg].location = kRegisterInRegister; + results->savedRegisters[reg].value = + ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0; + } + + for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { + results->savedRegisters[reg].location = kRegisterInCFA; + results->savedRegisters[reg].value = + ((int64_t)reg - UNW_SPARC_L0) * 4; + } + break; +#endif + } + break; +#else + (void)arch; +#endif + + default: + operand = opcode & 0x3F; + switch (opcode & 0xC0) { + case DW_CFA_offset: + reg = operand; + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64 + ") out of range", + reg); + return false; + } + offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) + * cieInfo.dataAlignFactor; + results->savedRegisters[reg].location = kRegisterInCFA; + results->savedRegisters[reg].value = offset; + _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", + operand, offset); + break; + case DW_CFA_advance_loc: + codeOffset += operand * cieInfo.codeAlignFactor; + _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n", + static_cast(codeOffset)); + break; + case DW_CFA_restore: + reg = operand; + if (reg > kMaxRegisterNumber) { + _LIBUNWIND_LOG("malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64 + ") out of range", + reg); + return false; + } + results->savedRegisters[reg] = initialState.savedRegisters[reg]; + _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n", + static_cast(operand)); + break; + default: + _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode); + return false; + } + } + } + + return true; +} + +} // namespace libunwind + +#endif // __DWARF_PARSER_HPP__ Index: head/contrib/libunwind/src/RWMutex.hpp =================================================================== --- head/contrib/libunwind/src/RWMutex.hpp (nonexistent) +++ head/contrib/libunwind/src/RWMutex.hpp (revision 345068) @@ -0,0 +1,77 @@ +//===----------------------------- Registers.hpp --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Abstract interface to shared reader/writer log, hiding platform and +// configuration differences. +// +//===----------------------------------------------------------------------===// + +#ifndef __RWMUTEX_HPP__ +#define __RWMUTEX_HPP__ + +#if defined(_WIN32) +#include +#elif !defined(_LIBUNWIND_HAS_NO_THREADS) +#include +#endif + +namespace libunwind { + +#if defined(_LIBUNWIND_HAS_NO_THREADS) + +class _LIBUNWIND_HIDDEN RWMutex { +public: + bool lock_shared() { return true; } + bool unlock_shared() { return true; } + bool lock() { return true; } + bool unlock() { return true; } +}; + +#elif defined(_WIN32) + +class _LIBUNWIND_HIDDEN RWMutex { +public: + bool lock_shared() { + AcquireSRWLockShared(&_lock); + return true; + } + bool unlock_shared() { + ReleaseSRWLockShared(&_lock); + return true; + } + bool lock() { + AcquireSRWLockExclusive(&_lock); + return true; + } + bool unlock() { + ReleaseSRWLockExclusive(&_lock); + return true; + } + +private: + SRWLOCK _lock = SRWLOCK_INIT; +}; + +#else + +class _LIBUNWIND_HIDDEN RWMutex { +public: + bool lock_shared() { return pthread_rwlock_rdlock(&_lock) == 0; } + bool unlock_shared() { return pthread_rwlock_unlock(&_lock) == 0; } + bool lock() { return pthread_rwlock_wrlock(&_lock) == 0; } + bool unlock() { return pthread_rwlock_unlock(&_lock) == 0; } + +private: + pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER; +}; + +#endif + +} // namespace libunwind + +#endif // __RWMUTEX_HPP__ Property changes on: head/contrib/libunwind/src/RWMutex.hpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/Registers.hpp =================================================================== --- head/contrib/libunwind/src/Registers.hpp (nonexistent) +++ head/contrib/libunwind/src/Registers.hpp (revision 345068) @@ -0,0 +1,3785 @@ +//===----------------------------- Registers.hpp --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Models register sets for supported processors. +// +//===----------------------------------------------------------------------===// + +#ifndef __REGISTERS_HPP__ +#define __REGISTERS_HPP__ + +#include +#include + +#include "libunwind.h" +#include "config.h" + +namespace libunwind { + +// For emulating 128-bit registers +struct v128 { uint32_t vec[4]; }; + +enum { + REGISTERS_X86, + REGISTERS_X86_64, + REGISTERS_PPC, + REGISTERS_PPC64, + REGISTERS_ARM64, + REGISTERS_ARM, + REGISTERS_OR1K, + REGISTERS_RISCV, + REGISTERS_MIPS_O32, + REGISTERS_MIPS_NEWABI, + REGISTERS_SPARC, +}; + +#if defined(_LIBUNWIND_TARGET_I386) +/// Registers_x86 holds the register state of a thread in a 32-bit intel +/// process. +class _LIBUNWIND_HIDDEN Registers_x86 { +public: + Registers_x86(); + Registers_x86(const void *registers); + + bool validRegister(int num) const; + uint32_t getRegister(int num) const; + void setRegister(int num, uint32_t value); + bool validFloatRegister(int) const { return false; } + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int) const { return false; } + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + static const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; } + static int getArch() { return REGISTERS_X86; } + + uint32_t getSP() const { return _registers.__esp; } + void setSP(uint32_t value) { _registers.__esp = value; } + uint32_t getIP() const { return _registers.__eip; } + void setIP(uint32_t value) { _registers.__eip = value; } + uint32_t getEBP() const { return _registers.__ebp; } + void setEBP(uint32_t value) { _registers.__ebp = value; } + uint32_t getEBX() const { return _registers.__ebx; } + void setEBX(uint32_t value) { _registers.__ebx = value; } + uint32_t getECX() const { return _registers.__ecx; } + void setECX(uint32_t value) { _registers.__ecx = value; } + uint32_t getEDX() const { return _registers.__edx; } + void setEDX(uint32_t value) { _registers.__edx = value; } + uint32_t getESI() const { return _registers.__esi; } + void setESI(uint32_t value) { _registers.__esi = value; } + uint32_t getEDI() const { return _registers.__edi; } + void setEDI(uint32_t value) { _registers.__edi = value; } + +private: + struct GPRs { + unsigned int __eax; + unsigned int __ebx; + unsigned int __ecx; + unsigned int __edx; + unsigned int __edi; + unsigned int __esi; + unsigned int __ebp; + unsigned int __esp; + unsigned int __ss; + unsigned int __eflags; + unsigned int __eip; + unsigned int __cs; + unsigned int __ds; + unsigned int __es; + unsigned int __fs; + unsigned int __gs; + }; + + GPRs _registers; +}; + +inline Registers_x86::Registers_x86(const void *registers) { + static_assert((check_fit::does_fit), + "x86 registers do not fit into unw_context_t"); + memcpy(&_registers, registers, sizeof(_registers)); +} + +inline Registers_x86::Registers_x86() { + memset(&_registers, 0, sizeof(_registers)); +} + +inline bool Registers_x86::validRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return true; + if (regNum == UNW_REG_SP) + return true; + if (regNum < 0) + return false; + if (regNum > 7) + return false; + return true; +} + +inline uint32_t Registers_x86::getRegister(int regNum) const { + switch (regNum) { + case UNW_REG_IP: + return _registers.__eip; + case UNW_REG_SP: + return _registers.__esp; + case UNW_X86_EAX: + return _registers.__eax; + case UNW_X86_ECX: + return _registers.__ecx; + case UNW_X86_EDX: + return _registers.__edx; + case UNW_X86_EBX: + return _registers.__ebx; +#if !defined(__APPLE__) + case UNW_X86_ESP: +#else + case UNW_X86_EBP: +#endif + return _registers.__ebp; +#if !defined(__APPLE__) + case UNW_X86_EBP: +#else + case UNW_X86_ESP: +#endif + return _registers.__esp; + case UNW_X86_ESI: + return _registers.__esi; + case UNW_X86_EDI: + return _registers.__edi; + } + _LIBUNWIND_ABORT("unsupported x86 register"); +} + +inline void Registers_x86::setRegister(int regNum, uint32_t value) { + switch (regNum) { + case UNW_REG_IP: + _registers.__eip = value; + return; + case UNW_REG_SP: + _registers.__esp = value; + return; + case UNW_X86_EAX: + _registers.__eax = value; + return; + case UNW_X86_ECX: + _registers.__ecx = value; + return; + case UNW_X86_EDX: + _registers.__edx = value; + return; + case UNW_X86_EBX: + _registers.__ebx = value; + return; +#if !defined(__APPLE__) + case UNW_X86_ESP: +#else + case UNW_X86_EBP: +#endif + _registers.__ebp = value; + return; +#if !defined(__APPLE__) + case UNW_X86_EBP: +#else + case UNW_X86_ESP: +#endif + _registers.__esp = value; + return; + case UNW_X86_ESI: + _registers.__esi = value; + return; + case UNW_X86_EDI: + _registers.__edi = value; + return; + } + _LIBUNWIND_ABORT("unsupported x86 register"); +} + +inline const char *Registers_x86::getRegisterName(int regNum) { + switch (regNum) { + case UNW_REG_IP: + return "ip"; + case UNW_REG_SP: + return "esp"; + case UNW_X86_EAX: + return "eax"; + case UNW_X86_ECX: + return "ecx"; + case UNW_X86_EDX: + return "edx"; + case UNW_X86_EBX: + return "ebx"; + case UNW_X86_EBP: + return "ebp"; + case UNW_X86_ESP: + return "esp"; + case UNW_X86_ESI: + return "esi"; + case UNW_X86_EDI: + return "edi"; + default: + return "unknown register"; + } +} + +inline double Registers_x86::getFloatRegister(int) const { + _LIBUNWIND_ABORT("no x86 float registers"); +} + +inline void Registers_x86::setFloatRegister(int, double) { + _LIBUNWIND_ABORT("no x86 float registers"); +} + +inline v128 Registers_x86::getVectorRegister(int) const { + _LIBUNWIND_ABORT("no x86 vector registers"); +} + +inline void Registers_x86::setVectorRegister(int, v128) { + _LIBUNWIND_ABORT("no x86 vector registers"); +} +#endif // _LIBUNWIND_TARGET_I386 + + +#if defined(_LIBUNWIND_TARGET_X86_64) +/// Registers_x86_64 holds the register state of a thread in a 64-bit intel +/// process. +class _LIBUNWIND_HIDDEN Registers_x86_64 { +public: + Registers_x86_64(); + Registers_x86_64(const void *registers); + + bool validRegister(int num) const; + uint64_t getRegister(int num) const; + void setRegister(int num, uint64_t value); + bool validFloatRegister(int) const { return false; } + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + static const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; } + static int getArch() { return REGISTERS_X86_64; } + + uint64_t getSP() const { return _registers.__rsp; } + void setSP(uint64_t value) { _registers.__rsp = value; } + uint64_t getIP() const { return _registers.__rip; } + void setIP(uint64_t value) { _registers.__rip = value; } + uint64_t getRBP() const { return _registers.__rbp; } + void setRBP(uint64_t value) { _registers.__rbp = value; } + uint64_t getRBX() const { return _registers.__rbx; } + void setRBX(uint64_t value) { _registers.__rbx = value; } + uint64_t getR12() const { return _registers.__r12; } + void setR12(uint64_t value) { _registers.__r12 = value; } + uint64_t getR13() const { return _registers.__r13; } + void setR13(uint64_t value) { _registers.__r13 = value; } + uint64_t getR14() const { return _registers.__r14; } + void setR14(uint64_t value) { _registers.__r14 = value; } + uint64_t getR15() const { return _registers.__r15; } + void setR15(uint64_t value) { _registers.__r15 = value; } + +private: + struct GPRs { + uint64_t __rax; + uint64_t __rbx; + uint64_t __rcx; + uint64_t __rdx; + uint64_t __rdi; + uint64_t __rsi; + uint64_t __rbp; + uint64_t __rsp; + uint64_t __r8; + uint64_t __r9; + uint64_t __r10; + uint64_t __r11; + uint64_t __r12; + uint64_t __r13; + uint64_t __r14; + uint64_t __r15; + uint64_t __rip; + uint64_t __rflags; + uint64_t __cs; + uint64_t __fs; + uint64_t __gs; +#if defined(_WIN64) + uint64_t __padding; // 16-byte align +#endif + }; + GPRs _registers; +#if defined(_WIN64) + v128 _xmm[16]; +#endif +}; + +inline Registers_x86_64::Registers_x86_64(const void *registers) { + static_assert((check_fit::does_fit), + "x86_64 registers do not fit into unw_context_t"); + memcpy(&_registers, registers, sizeof(_registers)); +} + +inline Registers_x86_64::Registers_x86_64() { + memset(&_registers, 0, sizeof(_registers)); +} + +inline bool Registers_x86_64::validRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return true; + if (regNum == UNW_REG_SP) + return true; + if (regNum < 0) + return false; + if (regNum > 15) + return false; + return true; +} + +inline uint64_t Registers_x86_64::getRegister(int regNum) const { + switch (regNum) { + case UNW_REG_IP: + return _registers.__rip; + case UNW_REG_SP: + return _registers.__rsp; + case UNW_X86_64_RAX: + return _registers.__rax; + case UNW_X86_64_RDX: + return _registers.__rdx; + case UNW_X86_64_RCX: + return _registers.__rcx; + case UNW_X86_64_RBX: + return _registers.__rbx; + case UNW_X86_64_RSI: + return _registers.__rsi; + case UNW_X86_64_RDI: + return _registers.__rdi; + case UNW_X86_64_RBP: + return _registers.__rbp; + case UNW_X86_64_RSP: + return _registers.__rsp; + case UNW_X86_64_R8: + return _registers.__r8; + case UNW_X86_64_R9: + return _registers.__r9; + case UNW_X86_64_R10: + return _registers.__r10; + case UNW_X86_64_R11: + return _registers.__r11; + case UNW_X86_64_R12: + return _registers.__r12; + case UNW_X86_64_R13: + return _registers.__r13; + case UNW_X86_64_R14: + return _registers.__r14; + case UNW_X86_64_R15: + return _registers.__r15; + } + _LIBUNWIND_ABORT("unsupported x86_64 register"); +} + +inline void Registers_x86_64::setRegister(int regNum, uint64_t value) { + switch (regNum) { + case UNW_REG_IP: + _registers.__rip = value; + return; + case UNW_REG_SP: + _registers.__rsp = value; + return; + case UNW_X86_64_RAX: + _registers.__rax = value; + return; + case UNW_X86_64_RDX: + _registers.__rdx = value; + return; + case UNW_X86_64_RCX: + _registers.__rcx = value; + return; + case UNW_X86_64_RBX: + _registers.__rbx = value; + return; + case UNW_X86_64_RSI: + _registers.__rsi = value; + return; + case UNW_X86_64_RDI: + _registers.__rdi = value; + return; + case UNW_X86_64_RBP: + _registers.__rbp = value; + return; + case UNW_X86_64_RSP: + _registers.__rsp = value; + return; + case UNW_X86_64_R8: + _registers.__r8 = value; + return; + case UNW_X86_64_R9: + _registers.__r9 = value; + return; + case UNW_X86_64_R10: + _registers.__r10 = value; + return; + case UNW_X86_64_R11: + _registers.__r11 = value; + return; + case UNW_X86_64_R12: + _registers.__r12 = value; + return; + case UNW_X86_64_R13: + _registers.__r13 = value; + return; + case UNW_X86_64_R14: + _registers.__r14 = value; + return; + case UNW_X86_64_R15: + _registers.__r15 = value; + return; + } + _LIBUNWIND_ABORT("unsupported x86_64 register"); +} + +inline const char *Registers_x86_64::getRegisterName(int regNum) { + switch (regNum) { + case UNW_REG_IP: + return "rip"; + case UNW_REG_SP: + return "rsp"; + case UNW_X86_64_RAX: + return "rax"; + case UNW_X86_64_RDX: + return "rdx"; + case UNW_X86_64_RCX: + return "rcx"; + case UNW_X86_64_RBX: + return "rbx"; + case UNW_X86_64_RSI: + return "rsi"; + case UNW_X86_64_RDI: + return "rdi"; + case UNW_X86_64_RBP: + return "rbp"; + case UNW_X86_64_RSP: + return "rsp"; + case UNW_X86_64_R8: + return "r8"; + case UNW_X86_64_R9: + return "r9"; + case UNW_X86_64_R10: + return "r10"; + case UNW_X86_64_R11: + return "r11"; + case UNW_X86_64_R12: + return "r12"; + case UNW_X86_64_R13: + return "r13"; + case UNW_X86_64_R14: + return "r14"; + case UNW_X86_64_R15: + return "r15"; + case UNW_X86_64_XMM0: + return "xmm0"; + case UNW_X86_64_XMM1: + return "xmm1"; + case UNW_X86_64_XMM2: + return "xmm2"; + case UNW_X86_64_XMM3: + return "xmm3"; + case UNW_X86_64_XMM4: + return "xmm4"; + case UNW_X86_64_XMM5: + return "xmm5"; + case UNW_X86_64_XMM6: + return "xmm6"; + case UNW_X86_64_XMM7: + return "xmm7"; + case UNW_X86_64_XMM8: + return "xmm8"; + case UNW_X86_64_XMM9: + return "xmm9"; + case UNW_X86_64_XMM10: + return "xmm10"; + case UNW_X86_64_XMM11: + return "xmm11"; + case UNW_X86_64_XMM12: + return "xmm12"; + case UNW_X86_64_XMM13: + return "xmm13"; + case UNW_X86_64_XMM14: + return "xmm14"; + case UNW_X86_64_XMM15: + return "xmm15"; + default: + return "unknown register"; + } +} + +inline double Registers_x86_64::getFloatRegister(int) const { + _LIBUNWIND_ABORT("no x86_64 float registers"); +} + +inline void Registers_x86_64::setFloatRegister(int, double) { + _LIBUNWIND_ABORT("no x86_64 float registers"); +} + +inline bool Registers_x86_64::validVectorRegister(int regNum) const { +#if defined(_WIN64) + if (regNum < UNW_X86_64_XMM0) + return false; + if (regNum > UNW_X86_64_XMM15) + return false; + return true; +#else + (void)regNum; // suppress unused parameter warning + return false; +#endif +} + +inline v128 Registers_x86_64::getVectorRegister(int regNum) const { +#if defined(_WIN64) + assert(validVectorRegister(regNum)); + return _xmm[regNum - UNW_X86_64_XMM0]; +#else + (void)regNum; // suppress unused parameter warning + _LIBUNWIND_ABORT("no x86_64 vector registers"); +#endif +} + +inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) { +#if defined(_WIN64) + assert(validVectorRegister(regNum)); + _xmm[regNum - UNW_X86_64_XMM0] = value; +#else + (void)regNum; (void)value; // suppress unused parameter warnings + _LIBUNWIND_ABORT("no x86_64 vector registers"); +#endif +} +#endif // _LIBUNWIND_TARGET_X86_64 + + +#if defined(_LIBUNWIND_TARGET_PPC) +/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC +/// process. +class _LIBUNWIND_HIDDEN Registers_ppc { +public: + Registers_ppc(); + Registers_ppc(const void *registers); + + bool validRegister(int num) const; + uint32_t getRegister(int num) const; + void setRegister(int num, uint32_t value); + bool validFloatRegister(int num) const; + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int num) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + static const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; } + static int getArch() { return REGISTERS_PPC; } + + uint64_t getSP() const { return _registers.__r1; } + void setSP(uint32_t value) { _registers.__r1 = value; } + uint64_t getIP() const { return _registers.__srr0; } + void setIP(uint32_t value) { _registers.__srr0 = value; } + +private: + struct ppc_thread_state_t { + unsigned int __srr0; /* Instruction address register (PC) */ + unsigned int __srr1; /* Machine state register (supervisor) */ + unsigned int __r0; + unsigned int __r1; + unsigned int __r2; + unsigned int __r3; + unsigned int __r4; + unsigned int __r5; + unsigned int __r6; + unsigned int __r7; + unsigned int __r8; + unsigned int __r9; + unsigned int __r10; + unsigned int __r11; + unsigned int __r12; + unsigned int __r13; + unsigned int __r14; + unsigned int __r15; + unsigned int __r16; + unsigned int __r17; + unsigned int __r18; + unsigned int __r19; + unsigned int __r20; + unsigned int __r21; + unsigned int __r22; + unsigned int __r23; + unsigned int __r24; + unsigned int __r25; + unsigned int __r26; + unsigned int __r27; + unsigned int __r28; + unsigned int __r29; + unsigned int __r30; + unsigned int __r31; + unsigned int __cr; /* Condition register */ + unsigned int __xer; /* User's integer exception register */ + unsigned int __lr; /* Link register */ + unsigned int __ctr; /* Count register */ + unsigned int __mq; /* MQ register (601 only) */ + unsigned int __vrsave; /* Vector Save Register */ + }; + + struct ppc_float_state_t { + double __fpregs[32]; + + unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */ + unsigned int __fpscr; /* floating point status register */ + }; + + ppc_thread_state_t _registers; + ppc_float_state_t _floatRegisters; + v128 _vectorRegisters[32]; // offset 424 +}; + +inline Registers_ppc::Registers_ppc(const void *registers) { + static_assert((check_fit::does_fit), + "ppc registers do not fit into unw_context_t"); + memcpy(&_registers, static_cast(registers), + sizeof(_registers)); + static_assert(sizeof(ppc_thread_state_t) == 160, + "expected float register offset to be 160"); + memcpy(&_floatRegisters, + static_cast(registers) + sizeof(ppc_thread_state_t), + sizeof(_floatRegisters)); + static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424, + "expected vector register offset to be 424 bytes"); + memcpy(_vectorRegisters, + static_cast(registers) + sizeof(ppc_thread_state_t) + + sizeof(ppc_float_state_t), + sizeof(_vectorRegisters)); +} + +inline Registers_ppc::Registers_ppc() { + memset(&_registers, 0, sizeof(_registers)); + memset(&_floatRegisters, 0, sizeof(_floatRegisters)); + memset(&_vectorRegisters, 0, sizeof(_vectorRegisters)); +} + +inline bool Registers_ppc::validRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return true; + if (regNum == UNW_REG_SP) + return true; + if (regNum == UNW_PPC_VRSAVE) + return true; + if (regNum < 0) + return false; + if (regNum <= UNW_PPC_R31) + return true; + if (regNum == UNW_PPC_MQ) + return true; + if (regNum == UNW_PPC_LR) + return true; + if (regNum == UNW_PPC_CTR) + return true; + if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7)) + return true; + return false; +} + +inline uint32_t Registers_ppc::getRegister(int regNum) const { + switch (regNum) { + case UNW_REG_IP: + return _registers.__srr0; + case UNW_REG_SP: + return _registers.__r1; + case UNW_PPC_R0: + return _registers.__r0; + case UNW_PPC_R1: + return _registers.__r1; + case UNW_PPC_R2: + return _registers.__r2; + case UNW_PPC_R3: + return _registers.__r3; + case UNW_PPC_R4: + return _registers.__r4; + case UNW_PPC_R5: + return _registers.__r5; + case UNW_PPC_R6: + return _registers.__r6; + case UNW_PPC_R7: + return _registers.__r7; + case UNW_PPC_R8: + return _registers.__r8; + case UNW_PPC_R9: + return _registers.__r9; + case UNW_PPC_R10: + return _registers.__r10; + case UNW_PPC_R11: + return _registers.__r11; + case UNW_PPC_R12: + return _registers.__r12; + case UNW_PPC_R13: + return _registers.__r13; + case UNW_PPC_R14: + return _registers.__r14; + case UNW_PPC_R15: + return _registers.__r15; + case UNW_PPC_R16: + return _registers.__r16; + case UNW_PPC_R17: + return _registers.__r17; + case UNW_PPC_R18: + return _registers.__r18; + case UNW_PPC_R19: + return _registers.__r19; + case UNW_PPC_R20: + return _registers.__r20; + case UNW_PPC_R21: + return _registers.__r21; + case UNW_PPC_R22: + return _registers.__r22; + case UNW_PPC_R23: + return _registers.__r23; + case UNW_PPC_R24: + return _registers.__r24; + case UNW_PPC_R25: + return _registers.__r25; + case UNW_PPC_R26: + return _registers.__r26; + case UNW_PPC_R27: + return _registers.__r27; + case UNW_PPC_R28: + return _registers.__r28; + case UNW_PPC_R29: + return _registers.__r29; + case UNW_PPC_R30: + return _registers.__r30; + case UNW_PPC_R31: + return _registers.__r31; + case UNW_PPC_LR: + return _registers.__lr; + case UNW_PPC_CR0: + return (_registers.__cr & 0xF0000000); + case UNW_PPC_CR1: + return (_registers.__cr & 0x0F000000); + case UNW_PPC_CR2: + return (_registers.__cr & 0x00F00000); + case UNW_PPC_CR3: + return (_registers.__cr & 0x000F0000); + case UNW_PPC_CR4: + return (_registers.__cr & 0x0000F000); + case UNW_PPC_CR5: + return (_registers.__cr & 0x00000F00); + case UNW_PPC_CR6: + return (_registers.__cr & 0x000000F0); + case UNW_PPC_CR7: + return (_registers.__cr & 0x0000000F); + case UNW_PPC_VRSAVE: + return _registers.__vrsave; + } + _LIBUNWIND_ABORT("unsupported ppc register"); +} + +inline void Registers_ppc::setRegister(int regNum, uint32_t value) { + //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value); + switch (regNum) { + case UNW_REG_IP: + _registers.__srr0 = value; + return; + case UNW_REG_SP: + _registers.__r1 = value; + return; + case UNW_PPC_R0: + _registers.__r0 = value; + return; + case UNW_PPC_R1: + _registers.__r1 = value; + return; + case UNW_PPC_R2: + _registers.__r2 = value; + return; + case UNW_PPC_R3: + _registers.__r3 = value; + return; + case UNW_PPC_R4: + _registers.__r4 = value; + return; + case UNW_PPC_R5: + _registers.__r5 = value; + return; + case UNW_PPC_R6: + _registers.__r6 = value; + return; + case UNW_PPC_R7: + _registers.__r7 = value; + return; + case UNW_PPC_R8: + _registers.__r8 = value; + return; + case UNW_PPC_R9: + _registers.__r9 = value; + return; + case UNW_PPC_R10: + _registers.__r10 = value; + return; + case UNW_PPC_R11: + _registers.__r11 = value; + return; + case UNW_PPC_R12: + _registers.__r12 = value; + return; + case UNW_PPC_R13: + _registers.__r13 = value; + return; + case UNW_PPC_R14: + _registers.__r14 = value; + return; + case UNW_PPC_R15: + _registers.__r15 = value; + return; + case UNW_PPC_R16: + _registers.__r16 = value; + return; + case UNW_PPC_R17: + _registers.__r17 = value; + return; + case UNW_PPC_R18: + _registers.__r18 = value; + return; + case UNW_PPC_R19: + _registers.__r19 = value; + return; + case UNW_PPC_R20: + _registers.__r20 = value; + return; + case UNW_PPC_R21: + _registers.__r21 = value; + return; + case UNW_PPC_R22: + _registers.__r22 = value; + return; + case UNW_PPC_R23: + _registers.__r23 = value; + return; + case UNW_PPC_R24: + _registers.__r24 = value; + return; + case UNW_PPC_R25: + _registers.__r25 = value; + return; + case UNW_PPC_R26: + _registers.__r26 = value; + return; + case UNW_PPC_R27: + _registers.__r27 = value; + return; + case UNW_PPC_R28: + _registers.__r28 = value; + return; + case UNW_PPC_R29: + _registers.__r29 = value; + return; + case UNW_PPC_R30: + _registers.__r30 = value; + return; + case UNW_PPC_R31: + _registers.__r31 = value; + return; + case UNW_PPC_MQ: + _registers.__mq = value; + return; + case UNW_PPC_LR: + _registers.__lr = value; + return; + case UNW_PPC_CTR: + _registers.__ctr = value; + return; + case UNW_PPC_CR0: + _registers.__cr &= 0x0FFFFFFF; + _registers.__cr |= (value & 0xF0000000); + return; + case UNW_PPC_CR1: + _registers.__cr &= 0xF0FFFFFF; + _registers.__cr |= (value & 0x0F000000); + return; + case UNW_PPC_CR2: + _registers.__cr &= 0xFF0FFFFF; + _registers.__cr |= (value & 0x00F00000); + return; + case UNW_PPC_CR3: + _registers.__cr &= 0xFFF0FFFF; + _registers.__cr |= (value & 0x000F0000); + return; + case UNW_PPC_CR4: + _registers.__cr &= 0xFFFF0FFF; + _registers.__cr |= (value & 0x0000F000); + return; + case UNW_PPC_CR5: + _registers.__cr &= 0xFFFFF0FF; + _registers.__cr |= (value & 0x00000F00); + return; + case UNW_PPC_CR6: + _registers.__cr &= 0xFFFFFF0F; + _registers.__cr |= (value & 0x000000F0); + return; + case UNW_PPC_CR7: + _registers.__cr &= 0xFFFFFFF0; + _registers.__cr |= (value & 0x0000000F); + return; + case UNW_PPC_VRSAVE: + _registers.__vrsave = value; + return; + // not saved + return; + case UNW_PPC_XER: + _registers.__xer = value; + return; + case UNW_PPC_AP: + case UNW_PPC_VSCR: + case UNW_PPC_SPEFSCR: + // not saved + return; + } + _LIBUNWIND_ABORT("unsupported ppc register"); +} + +inline bool Registers_ppc::validFloatRegister(int regNum) const { + if (regNum < UNW_PPC_F0) + return false; + if (regNum > UNW_PPC_F31) + return false; + return true; +} + +inline double Registers_ppc::getFloatRegister(int regNum) const { + assert(validFloatRegister(regNum)); + return _floatRegisters.__fpregs[regNum - UNW_PPC_F0]; +} + +inline void Registers_ppc::setFloatRegister(int regNum, double value) { + assert(validFloatRegister(regNum)); + _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value; +} + +inline bool Registers_ppc::validVectorRegister(int regNum) const { + if (regNum < UNW_PPC_V0) + return false; + if (regNum > UNW_PPC_V31) + return false; + return true; +} + +inline v128 Registers_ppc::getVectorRegister(int regNum) const { + assert(validVectorRegister(regNum)); + v128 result = _vectorRegisters[regNum - UNW_PPC_V0]; + return result; +} + +inline void Registers_ppc::setVectorRegister(int regNum, v128 value) { + assert(validVectorRegister(regNum)); + _vectorRegisters[regNum - UNW_PPC_V0] = value; +} + +inline const char *Registers_ppc::getRegisterName(int regNum) { + switch (regNum) { + case UNW_REG_IP: + return "ip"; + case UNW_REG_SP: + return "sp"; + case UNW_PPC_R0: + return "r0"; + case UNW_PPC_R1: + return "r1"; + case UNW_PPC_R2: + return "r2"; + case UNW_PPC_R3: + return "r3"; + case UNW_PPC_R4: + return "r4"; + case UNW_PPC_R5: + return "r5"; + case UNW_PPC_R6: + return "r6"; + case UNW_PPC_R7: + return "r7"; + case UNW_PPC_R8: + return "r8"; + case UNW_PPC_R9: + return "r9"; + case UNW_PPC_R10: + return "r10"; + case UNW_PPC_R11: + return "r11"; + case UNW_PPC_R12: + return "r12"; + case UNW_PPC_R13: + return "r13"; + case UNW_PPC_R14: + return "r14"; + case UNW_PPC_R15: + return "r15"; + case UNW_PPC_R16: + return "r16"; + case UNW_PPC_R17: + return "r17"; + case UNW_PPC_R18: + return "r18"; + case UNW_PPC_R19: + return "r19"; + case UNW_PPC_R20: + return "r20"; + case UNW_PPC_R21: + return "r21"; + case UNW_PPC_R22: + return "r22"; + case UNW_PPC_R23: + return "r23"; + case UNW_PPC_R24: + return "r24"; + case UNW_PPC_R25: + return "r25"; + case UNW_PPC_R26: + return "r26"; + case UNW_PPC_R27: + return "r27"; + case UNW_PPC_R28: + return "r28"; + case UNW_PPC_R29: + return "r29"; + case UNW_PPC_R30: + return "r30"; + case UNW_PPC_R31: + return "r31"; + case UNW_PPC_F0: + return "fp0"; + case UNW_PPC_F1: + return "fp1"; + case UNW_PPC_F2: + return "fp2"; + case UNW_PPC_F3: + return "fp3"; + case UNW_PPC_F4: + return "fp4"; + case UNW_PPC_F5: + return "fp5"; + case UNW_PPC_F6: + return "fp6"; + case UNW_PPC_F7: + return "fp7"; + case UNW_PPC_F8: + return "fp8"; + case UNW_PPC_F9: + return "fp9"; + case UNW_PPC_F10: + return "fp10"; + case UNW_PPC_F11: + return "fp11"; + case UNW_PPC_F12: + return "fp12"; + case UNW_PPC_F13: + return "fp13"; + case UNW_PPC_F14: + return "fp14"; + case UNW_PPC_F15: + return "fp15"; + case UNW_PPC_F16: + return "fp16"; + case UNW_PPC_F17: + return "fp17"; + case UNW_PPC_F18: + return "fp18"; + case UNW_PPC_F19: + return "fp19"; + case UNW_PPC_F20: + return "fp20"; + case UNW_PPC_F21: + return "fp21"; + case UNW_PPC_F22: + return "fp22"; + case UNW_PPC_F23: + return "fp23"; + case UNW_PPC_F24: + return "fp24"; + case UNW_PPC_F25: + return "fp25"; + case UNW_PPC_F26: + return "fp26"; + case UNW_PPC_F27: + return "fp27"; + case UNW_PPC_F28: + return "fp28"; + case UNW_PPC_F29: + return "fp29"; + case UNW_PPC_F30: + return "fp30"; + case UNW_PPC_F31: + return "fp31"; + case UNW_PPC_LR: + return "lr"; + default: + return "unknown register"; + } + +} +#endif // _LIBUNWIND_TARGET_PPC + +#if defined(_LIBUNWIND_TARGET_PPC64) +/// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC +/// process. +class _LIBUNWIND_HIDDEN Registers_ppc64 { +public: + Registers_ppc64(); + Registers_ppc64(const void *registers); + + bool validRegister(int num) const; + uint64_t getRegister(int num) const; + void setRegister(int num, uint64_t value); + bool validFloatRegister(int num) const; + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int num) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + static const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; } + static int getArch() { return REGISTERS_PPC64; } + + uint64_t getSP() const { return _registers.__r1; } + void setSP(uint64_t value) { _registers.__r1 = value; } + uint64_t getIP() const { return _registers.__srr0; } + void setIP(uint64_t value) { _registers.__srr0 = value; } + +private: + struct ppc64_thread_state_t { + uint64_t __srr0; // Instruction address register (PC) + uint64_t __srr1; // Machine state register (supervisor) + uint64_t __r0; + uint64_t __r1; + uint64_t __r2; + uint64_t __r3; + uint64_t __r4; + uint64_t __r5; + uint64_t __r6; + uint64_t __r7; + uint64_t __r8; + uint64_t __r9; + uint64_t __r10; + uint64_t __r11; + uint64_t __r12; + uint64_t __r13; + uint64_t __r14; + uint64_t __r15; + uint64_t __r16; + uint64_t __r17; + uint64_t __r18; + uint64_t __r19; + uint64_t __r20; + uint64_t __r21; + uint64_t __r22; + uint64_t __r23; + uint64_t __r24; + uint64_t __r25; + uint64_t __r26; + uint64_t __r27; + uint64_t __r28; + uint64_t __r29; + uint64_t __r30; + uint64_t __r31; + uint64_t __cr; // Condition register + uint64_t __xer; // User's integer exception register + uint64_t __lr; // Link register + uint64_t __ctr; // Count register + uint64_t __vrsave; // Vector Save Register + }; + + union ppc64_vsr_t { + struct asfloat_s { + double f; + uint64_t v2; + } asfloat; + v128 v; + }; + + ppc64_thread_state_t _registers; + ppc64_vsr_t _vectorScalarRegisters[64]; + + static int getVectorRegNum(int num); +}; + +inline Registers_ppc64::Registers_ppc64(const void *registers) { + static_assert((check_fit::does_fit), + "ppc64 registers do not fit into unw_context_t"); + memcpy(&_registers, static_cast(registers), + sizeof(_registers)); + static_assert(sizeof(_registers) == 312, + "expected vector scalar register offset to be 312"); + memcpy(&_vectorScalarRegisters, + static_cast(registers) + sizeof(_registers), + sizeof(_vectorScalarRegisters)); + static_assert(sizeof(_registers) + + sizeof(_vectorScalarRegisters) == 1336, + "expected vector register offset to be 1336 bytes"); +} + +inline Registers_ppc64::Registers_ppc64() { + memset(&_registers, 0, sizeof(_registers)); + memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters)); +} + +inline bool Registers_ppc64::validRegister(int regNum) const { + switch (regNum) { + case UNW_REG_IP: + case UNW_REG_SP: + case UNW_PPC64_XER: + case UNW_PPC64_LR: + case UNW_PPC64_CTR: + case UNW_PPC64_VRSAVE: + return true; + } + + if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31) + return true; + if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7) + return true; + + return false; +} + +inline uint64_t Registers_ppc64::getRegister(int regNum) const { + switch (regNum) { + case UNW_REG_IP: + return _registers.__srr0; + case UNW_PPC64_R0: + return _registers.__r0; + case UNW_PPC64_R1: + case UNW_REG_SP: + return _registers.__r1; + case UNW_PPC64_R2: + return _registers.__r2; + case UNW_PPC64_R3: + return _registers.__r3; + case UNW_PPC64_R4: + return _registers.__r4; + case UNW_PPC64_R5: + return _registers.__r5; + case UNW_PPC64_R6: + return _registers.__r6; + case UNW_PPC64_R7: + return _registers.__r7; + case UNW_PPC64_R8: + return _registers.__r8; + case UNW_PPC64_R9: + return _registers.__r9; + case UNW_PPC64_R10: + return _registers.__r10; + case UNW_PPC64_R11: + return _registers.__r11; + case UNW_PPC64_R12: + return _registers.__r12; + case UNW_PPC64_R13: + return _registers.__r13; + case UNW_PPC64_R14: + return _registers.__r14; + case UNW_PPC64_R15: + return _registers.__r15; + case UNW_PPC64_R16: + return _registers.__r16; + case UNW_PPC64_R17: + return _registers.__r17; + case UNW_PPC64_R18: + return _registers.__r18; + case UNW_PPC64_R19: + return _registers.__r19; + case UNW_PPC64_R20: + return _registers.__r20; + case UNW_PPC64_R21: + return _registers.__r21; + case UNW_PPC64_R22: + return _registers.__r22; + case UNW_PPC64_R23: + return _registers.__r23; + case UNW_PPC64_R24: + return _registers.__r24; + case UNW_PPC64_R25: + return _registers.__r25; + case UNW_PPC64_R26: + return _registers.__r26; + case UNW_PPC64_R27: + return _registers.__r27; + case UNW_PPC64_R28: + return _registers.__r28; + case UNW_PPC64_R29: + return _registers.__r29; + case UNW_PPC64_R30: + return _registers.__r30; + case UNW_PPC64_R31: + return _registers.__r31; + case UNW_PPC64_CR0: + return (_registers.__cr & 0xF0000000); + case UNW_PPC64_CR1: + return (_registers.__cr & 0x0F000000); + case UNW_PPC64_CR2: + return (_registers.__cr & 0x00F00000); + case UNW_PPC64_CR3: + return (_registers.__cr & 0x000F0000); + case UNW_PPC64_CR4: + return (_registers.__cr & 0x0000F000); + case UNW_PPC64_CR5: + return (_registers.__cr & 0x00000F00); + case UNW_PPC64_CR6: + return (_registers.__cr & 0x000000F0); + case UNW_PPC64_CR7: + return (_registers.__cr & 0x0000000F); + case UNW_PPC64_XER: + return _registers.__xer; + case UNW_PPC64_LR: + return _registers.__lr; + case UNW_PPC64_CTR: + return _registers.__ctr; + case UNW_PPC64_VRSAVE: + return _registers.__vrsave; + } + _LIBUNWIND_ABORT("unsupported ppc64 register"); +} + +inline void Registers_ppc64::setRegister(int regNum, uint64_t value) { + switch (regNum) { + case UNW_REG_IP: + _registers.__srr0 = value; + return; + case UNW_PPC64_R0: + _registers.__r0 = value; + return; + case UNW_PPC64_R1: + case UNW_REG_SP: + _registers.__r1 = value; + return; + case UNW_PPC64_R2: + _registers.__r2 = value; + return; + case UNW_PPC64_R3: + _registers.__r3 = value; + return; + case UNW_PPC64_R4: + _registers.__r4 = value; + return; + case UNW_PPC64_R5: + _registers.__r5 = value; + return; + case UNW_PPC64_R6: + _registers.__r6 = value; + return; + case UNW_PPC64_R7: + _registers.__r7 = value; + return; + case UNW_PPC64_R8: + _registers.__r8 = value; + return; + case UNW_PPC64_R9: + _registers.__r9 = value; + return; + case UNW_PPC64_R10: + _registers.__r10 = value; + return; + case UNW_PPC64_R11: + _registers.__r11 = value; + return; + case UNW_PPC64_R12: + _registers.__r12 = value; + return; + case UNW_PPC64_R13: + _registers.__r13 = value; + return; + case UNW_PPC64_R14: + _registers.__r14 = value; + return; + case UNW_PPC64_R15: + _registers.__r15 = value; + return; + case UNW_PPC64_R16: + _registers.__r16 = value; + return; + case UNW_PPC64_R17: + _registers.__r17 = value; + return; + case UNW_PPC64_R18: + _registers.__r18 = value; + return; + case UNW_PPC64_R19: + _registers.__r19 = value; + return; + case UNW_PPC64_R20: + _registers.__r20 = value; + return; + case UNW_PPC64_R21: + _registers.__r21 = value; + return; + case UNW_PPC64_R22: + _registers.__r22 = value; + return; + case UNW_PPC64_R23: + _registers.__r23 = value; + return; + case UNW_PPC64_R24: + _registers.__r24 = value; + return; + case UNW_PPC64_R25: + _registers.__r25 = value; + return; + case UNW_PPC64_R26: + _registers.__r26 = value; + return; + case UNW_PPC64_R27: + _registers.__r27 = value; + return; + case UNW_PPC64_R28: + _registers.__r28 = value; + return; + case UNW_PPC64_R29: + _registers.__r29 = value; + return; + case UNW_PPC64_R30: + _registers.__r30 = value; + return; + case UNW_PPC64_R31: + _registers.__r31 = value; + return; + case UNW_PPC64_CR0: + _registers.__cr &= 0x0FFFFFFF; + _registers.__cr |= (value & 0xF0000000); + return; + case UNW_PPC64_CR1: + _registers.__cr &= 0xF0FFFFFF; + _registers.__cr |= (value & 0x0F000000); + return; + case UNW_PPC64_CR2: + _registers.__cr &= 0xFF0FFFFF; + _registers.__cr |= (value & 0x00F00000); + return; + case UNW_PPC64_CR3: + _registers.__cr &= 0xFFF0FFFF; + _registers.__cr |= (value & 0x000F0000); + return; + case UNW_PPC64_CR4: + _registers.__cr &= 0xFFFF0FFF; + _registers.__cr |= (value & 0x0000F000); + return; + case UNW_PPC64_CR5: + _registers.__cr &= 0xFFFFF0FF; + _registers.__cr |= (value & 0x00000F00); + return; + case UNW_PPC64_CR6: + _registers.__cr &= 0xFFFFFF0F; + _registers.__cr |= (value & 0x000000F0); + return; + case UNW_PPC64_CR7: + _registers.__cr &= 0xFFFFFFF0; + _registers.__cr |= (value & 0x0000000F); + return; + case UNW_PPC64_XER: + _registers.__xer = value; + return; + case UNW_PPC64_LR: + _registers.__lr = value; + return; + case UNW_PPC64_CTR: + _registers.__ctr = value; + return; + case UNW_PPC64_VRSAVE: + _registers.__vrsave = value; + return; + } + _LIBUNWIND_ABORT("unsupported ppc64 register"); +} + +inline bool Registers_ppc64::validFloatRegister(int regNum) const { + return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31; +} + +inline double Registers_ppc64::getFloatRegister(int regNum) const { + assert(validFloatRegister(regNum)); + return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f; +} + +inline void Registers_ppc64::setFloatRegister(int regNum, double value) { + assert(validFloatRegister(regNum)); + _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value; +} + +inline bool Registers_ppc64::validVectorRegister(int regNum) const { +#ifdef PPC64_HAS_VMX + if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31) + return true; + if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63) + return true; +#else + if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31) + return true; +#endif + return false; +} + +inline int Registers_ppc64::getVectorRegNum(int num) +{ + if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31) + return num - UNW_PPC64_VS0; + else + return num - UNW_PPC64_VS32 + 32; +} + +inline v128 Registers_ppc64::getVectorRegister(int regNum) const { + assert(validVectorRegister(regNum)); + return _vectorScalarRegisters[getVectorRegNum(regNum)].v; +} + +inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) { + assert(validVectorRegister(regNum)); + _vectorScalarRegisters[getVectorRegNum(regNum)].v = value; +} + +inline const char *Registers_ppc64::getRegisterName(int regNum) { + switch (regNum) { + case UNW_REG_IP: + return "ip"; + case UNW_REG_SP: + return "sp"; + case UNW_PPC64_R0: + return "r0"; + case UNW_PPC64_R1: + return "r1"; + case UNW_PPC64_R2: + return "r2"; + case UNW_PPC64_R3: + return "r3"; + case UNW_PPC64_R4: + return "r4"; + case UNW_PPC64_R5: + return "r5"; + case UNW_PPC64_R6: + return "r6"; + case UNW_PPC64_R7: + return "r7"; + case UNW_PPC64_R8: + return "r8"; + case UNW_PPC64_R9: + return "r9"; + case UNW_PPC64_R10: + return "r10"; + case UNW_PPC64_R11: + return "r11"; + case UNW_PPC64_R12: + return "r12"; + case UNW_PPC64_R13: + return "r13"; + case UNW_PPC64_R14: + return "r14"; + case UNW_PPC64_R15: + return "r15"; + case UNW_PPC64_R16: + return "r16"; + case UNW_PPC64_R17: + return "r17"; + case UNW_PPC64_R18: + return "r18"; + case UNW_PPC64_R19: + return "r19"; + case UNW_PPC64_R20: + return "r20"; + case UNW_PPC64_R21: + return "r21"; + case UNW_PPC64_R22: + return "r22"; + case UNW_PPC64_R23: + return "r23"; + case UNW_PPC64_R24: + return "r24"; + case UNW_PPC64_R25: + return "r25"; + case UNW_PPC64_R26: + return "r26"; + case UNW_PPC64_R27: + return "r27"; + case UNW_PPC64_R28: + return "r28"; + case UNW_PPC64_R29: + return "r29"; + case UNW_PPC64_R30: + return "r30"; + case UNW_PPC64_R31: + return "r31"; + case UNW_PPC64_CR0: + return "cr0"; + case UNW_PPC64_CR1: + return "cr1"; + case UNW_PPC64_CR2: + return "cr2"; + case UNW_PPC64_CR3: + return "cr3"; + case UNW_PPC64_CR4: + return "cr4"; + case UNW_PPC64_CR5: + return "cr5"; + case UNW_PPC64_CR6: + return "cr6"; + case UNW_PPC64_CR7: + return "cr7"; + case UNW_PPC64_XER: + return "xer"; + case UNW_PPC64_LR: + return "lr"; + case UNW_PPC64_CTR: + return "ctr"; + case UNW_PPC64_VRSAVE: + return "vrsave"; + case UNW_PPC64_F0: + return "fp0"; + case UNW_PPC64_F1: + return "fp1"; + case UNW_PPC64_F2: + return "fp2"; + case UNW_PPC64_F3: + return "fp3"; + case UNW_PPC64_F4: + return "fp4"; + case UNW_PPC64_F5: + return "fp5"; + case UNW_PPC64_F6: + return "fp6"; + case UNW_PPC64_F7: + return "fp7"; + case UNW_PPC64_F8: + return "fp8"; + case UNW_PPC64_F9: + return "fp9"; + case UNW_PPC64_F10: + return "fp10"; + case UNW_PPC64_F11: + return "fp11"; + case UNW_PPC64_F12: + return "fp12"; + case UNW_PPC64_F13: + return "fp13"; + case UNW_PPC64_F14: + return "fp14"; + case UNW_PPC64_F15: + return "fp15"; + case UNW_PPC64_F16: + return "fp16"; + case UNW_PPC64_F17: + return "fp17"; + case UNW_PPC64_F18: + return "fp18"; + case UNW_PPC64_F19: + return "fp19"; + case UNW_PPC64_F20: + return "fp20"; + case UNW_PPC64_F21: + return "fp21"; + case UNW_PPC64_F22: + return "fp22"; + case UNW_PPC64_F23: + return "fp23"; + case UNW_PPC64_F24: + return "fp24"; + case UNW_PPC64_F25: + return "fp25"; + case UNW_PPC64_F26: + return "fp26"; + case UNW_PPC64_F27: + return "fp27"; + case UNW_PPC64_F28: + return "fp28"; + case UNW_PPC64_F29: + return "fp29"; + case UNW_PPC64_F30: + return "fp30"; + case UNW_PPC64_F31: + return "fp31"; + case UNW_PPC64_V0: + return "v0"; + case UNW_PPC64_V1: + return "v1"; + case UNW_PPC64_V2: + return "v2"; + case UNW_PPC64_V3: + return "v3"; + case UNW_PPC64_V4: + return "v4"; + case UNW_PPC64_V5: + return "v5"; + case UNW_PPC64_V6: + return "v6"; + case UNW_PPC64_V7: + return "v7"; + case UNW_PPC64_V8: + return "v8"; + case UNW_PPC64_V9: + return "v9"; + case UNW_PPC64_V10: + return "v10"; + case UNW_PPC64_V11: + return "v11"; + case UNW_PPC64_V12: + return "v12"; + case UNW_PPC64_V13: + return "v13"; + case UNW_PPC64_V14: + return "v14"; + case UNW_PPC64_V15: + return "v15"; + case UNW_PPC64_V16: + return "v16"; + case UNW_PPC64_V17: + return "v17"; + case UNW_PPC64_V18: + return "v18"; + case UNW_PPC64_V19: + return "v19"; + case UNW_PPC64_V20: + return "v20"; + case UNW_PPC64_V21: + return "v21"; + case UNW_PPC64_V22: + return "v22"; + case UNW_PPC64_V23: + return "v23"; + case UNW_PPC64_V24: + return "v24"; + case UNW_PPC64_V25: + return "v25"; + case UNW_PPC64_V26: + return "v26"; + case UNW_PPC64_V27: + return "v27"; + case UNW_PPC64_V28: + return "v28"; + case UNW_PPC64_V29: + return "v29"; + case UNW_PPC64_V30: + return "v30"; + case UNW_PPC64_V31: + return "v31"; + } + return "unknown register"; +} +#endif // _LIBUNWIND_TARGET_PPC64 + + +#if defined(_LIBUNWIND_TARGET_AARCH64) +/// Registers_arm64 holds the register state of a thread in a 64-bit arm +/// process. +class _LIBUNWIND_HIDDEN Registers_arm64 { +public: + Registers_arm64(); + Registers_arm64(const void *registers); + + bool validRegister(int num) const; + uint64_t getRegister(int num) const; + void setRegister(int num, uint64_t value); + bool validFloatRegister(int num) const; + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int num) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + static const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } + static int getArch() { return REGISTERS_ARM64; } + + uint64_t getSP() const { return _registers.__sp; } + void setSP(uint64_t value) { _registers.__sp = value; } + uint64_t getIP() const { return _registers.__pc; } + void setIP(uint64_t value) { _registers.__pc = value; } + uint64_t getFP() const { return _registers.__fp; } + void setFP(uint64_t value) { _registers.__fp = value; } + +private: + struct GPRs { + uint64_t __x[29]; // x0-x28 + uint64_t __fp; // Frame pointer x29 + uint64_t __lr; // Link register x30 + uint64_t __sp; // Stack pointer x31 + uint64_t __pc; // Program counter + uint64_t __ra_sign_state; // RA sign state register + }; + + GPRs _registers; + double _vectorHalfRegisters[32]; + // Currently only the lower double in 128-bit vectore registers + // is perserved during unwinding. We could define new register + // numbers (> 96) which mean whole vector registers, then this + // struct would need to change to contain whole vector registers. +}; + +inline Registers_arm64::Registers_arm64(const void *registers) { + static_assert((check_fit::does_fit), + "arm64 registers do not fit into unw_context_t"); + memcpy(&_registers, registers, sizeof(_registers)); + static_assert(sizeof(GPRs) == 0x110, + "expected VFP registers to be at offset 272"); + memcpy(_vectorHalfRegisters, + static_cast(registers) + sizeof(GPRs), + sizeof(_vectorHalfRegisters)); +} + +inline Registers_arm64::Registers_arm64() { + memset(&_registers, 0, sizeof(_registers)); + memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters)); +} + +inline bool Registers_arm64::validRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return true; + if (regNum == UNW_REG_SP) + return true; + if (regNum < 0) + return false; + if (regNum > 95) + return false; + if (regNum == UNW_ARM64_RA_SIGN_STATE) + return true; + if ((regNum > 31) && (regNum < 64)) + return false; + return true; +} + +inline uint64_t Registers_arm64::getRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return _registers.__pc; + if (regNum == UNW_REG_SP) + return _registers.__sp; + if (regNum == UNW_ARM64_RA_SIGN_STATE) + return _registers.__ra_sign_state; + if ((regNum >= 0) && (regNum < 32)) + return _registers.__x[regNum]; + _LIBUNWIND_ABORT("unsupported arm64 register"); +} + +inline void Registers_arm64::setRegister(int regNum, uint64_t value) { + if (regNum == UNW_REG_IP) + _registers.__pc = value; + else if (regNum == UNW_REG_SP) + _registers.__sp = value; + else if (regNum == UNW_ARM64_RA_SIGN_STATE) + _registers.__ra_sign_state = value; + else if ((regNum >= 0) && (regNum < 32)) + _registers.__x[regNum] = value; + else + _LIBUNWIND_ABORT("unsupported arm64 register"); +} + +inline const char *Registers_arm64::getRegisterName(int regNum) { + switch (regNum) { + case UNW_REG_IP: + return "pc"; + case UNW_REG_SP: + return "sp"; + case UNW_ARM64_X0: + return "x0"; + case UNW_ARM64_X1: + return "x1"; + case UNW_ARM64_X2: + return "x2"; + case UNW_ARM64_X3: + return "x3"; + case UNW_ARM64_X4: + return "x4"; + case UNW_ARM64_X5: + return "x5"; + case UNW_ARM64_X6: + return "x6"; + case UNW_ARM64_X7: + return "x7"; + case UNW_ARM64_X8: + return "x8"; + case UNW_ARM64_X9: + return "x9"; + case UNW_ARM64_X10: + return "x10"; + case UNW_ARM64_X11: + return "x11"; + case UNW_ARM64_X12: + return "x12"; + case UNW_ARM64_X13: + return "x13"; + case UNW_ARM64_X14: + return "x14"; + case UNW_ARM64_X15: + return "x15"; + case UNW_ARM64_X16: + return "x16"; + case UNW_ARM64_X17: + return "x17"; + case UNW_ARM64_X18: + return "x18"; + case UNW_ARM64_X19: + return "x19"; + case UNW_ARM64_X20: + return "x20"; + case UNW_ARM64_X21: + return "x21"; + case UNW_ARM64_X22: + return "x22"; + case UNW_ARM64_X23: + return "x23"; + case UNW_ARM64_X24: + return "x24"; + case UNW_ARM64_X25: + return "x25"; + case UNW_ARM64_X26: + return "x26"; + case UNW_ARM64_X27: + return "x27"; + case UNW_ARM64_X28: + return "x28"; + case UNW_ARM64_X29: + return "fp"; + case UNW_ARM64_X30: + return "lr"; + case UNW_ARM64_X31: + return "sp"; + case UNW_ARM64_D0: + return "d0"; + case UNW_ARM64_D1: + return "d1"; + case UNW_ARM64_D2: + return "d2"; + case UNW_ARM64_D3: + return "d3"; + case UNW_ARM64_D4: + return "d4"; + case UNW_ARM64_D5: + return "d5"; + case UNW_ARM64_D6: + return "d6"; + case UNW_ARM64_D7: + return "d7"; + case UNW_ARM64_D8: + return "d8"; + case UNW_ARM64_D9: + return "d9"; + case UNW_ARM64_D10: + return "d10"; + case UNW_ARM64_D11: + return "d11"; + case UNW_ARM64_D12: + return "d12"; + case UNW_ARM64_D13: + return "d13"; + case UNW_ARM64_D14: + return "d14"; + case UNW_ARM64_D15: + return "d15"; + case UNW_ARM64_D16: + return "d16"; + case UNW_ARM64_D17: + return "d17"; + case UNW_ARM64_D18: + return "d18"; + case UNW_ARM64_D19: + return "d19"; + case UNW_ARM64_D20: + return "d20"; + case UNW_ARM64_D21: + return "d21"; + case UNW_ARM64_D22: + return "d22"; + case UNW_ARM64_D23: + return "d23"; + case UNW_ARM64_D24: + return "d24"; + case UNW_ARM64_D25: + return "d25"; + case UNW_ARM64_D26: + return "d26"; + case UNW_ARM64_D27: + return "d27"; + case UNW_ARM64_D28: + return "d28"; + case UNW_ARM64_D29: + return "d29"; + case UNW_ARM64_D30: + return "d30"; + case UNW_ARM64_D31: + return "d31"; + default: + return "unknown register"; + } +} + +inline bool Registers_arm64::validFloatRegister(int regNum) const { + if (regNum < UNW_ARM64_D0) + return false; + if (regNum > UNW_ARM64_D31) + return false; + return true; +} + +inline double Registers_arm64::getFloatRegister(int regNum) const { + assert(validFloatRegister(regNum)); + return _vectorHalfRegisters[regNum - UNW_ARM64_D0]; +} + +inline void Registers_arm64::setFloatRegister(int regNum, double value) { + assert(validFloatRegister(regNum)); + _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value; +} + +inline bool Registers_arm64::validVectorRegister(int) const { + return false; +} + +inline v128 Registers_arm64::getVectorRegister(int) const { + _LIBUNWIND_ABORT("no arm64 vector register support yet"); +} + +inline void Registers_arm64::setVectorRegister(int, v128) { + _LIBUNWIND_ABORT("no arm64 vector register support yet"); +} +#endif // _LIBUNWIND_TARGET_AARCH64 + +#if defined(_LIBUNWIND_TARGET_ARM) +/// Registers_arm holds the register state of a thread in a 32-bit arm +/// process. +/// +/// NOTE: Assumes VFPv3. On ARM processors without a floating point unit, +/// this uses more memory than required. +class _LIBUNWIND_HIDDEN Registers_arm { +public: + Registers_arm(); + Registers_arm(const void *registers); + + bool validRegister(int num) const; + uint32_t getRegister(int num) const; + void setRegister(int num, uint32_t value); + bool validFloatRegister(int num) const; + unw_fpreg_t getFloatRegister(int num); + void setFloatRegister(int num, unw_fpreg_t value); + bool validVectorRegister(int num) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + static const char *getRegisterName(int num); + void jumpto() { + restoreSavedFloatRegisters(); + restoreCoreAndJumpTo(); + } + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; } + static int getArch() { return REGISTERS_ARM; } + + uint32_t getSP() const { return _registers.__sp; } + void setSP(uint32_t value) { _registers.__sp = value; } + uint32_t getIP() const { return _registers.__pc; } + void setIP(uint32_t value) { _registers.__pc = value; } + + void saveVFPAsX() { + assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15); + _use_X_for_vfp_save = true; + } + + void restoreSavedFloatRegisters() { + if (_saved_vfp_d0_d15) { + if (_use_X_for_vfp_save) + restoreVFPWithFLDMX(_vfp_d0_d15_pad); + else + restoreVFPWithFLDMD(_vfp_d0_d15_pad); + } + if (_saved_vfp_d16_d31) + restoreVFPv3(_vfp_d16_d31); +#if defined(__ARM_WMMX) + if (_saved_iwmmx) + restoreiWMMX(_iwmmx); + if (_saved_iwmmx_control) + restoreiWMMXControl(_iwmmx_control); +#endif + } + +private: + struct GPRs { + uint32_t __r[13]; // r0-r12 + uint32_t __sp; // Stack pointer r13 + uint32_t __lr; // Link register r14 + uint32_t __pc; // Program counter r15 + }; + + static void saveVFPWithFSTMD(unw_fpreg_t*); + static void saveVFPWithFSTMX(unw_fpreg_t*); + static void saveVFPv3(unw_fpreg_t*); + static void restoreVFPWithFLDMD(unw_fpreg_t*); + static void restoreVFPWithFLDMX(unw_fpreg_t*); + static void restoreVFPv3(unw_fpreg_t*); +#if defined(__ARM_WMMX) + static void saveiWMMX(unw_fpreg_t*); + static void saveiWMMXControl(uint32_t*); + static void restoreiWMMX(unw_fpreg_t*); + static void restoreiWMMXControl(uint32_t*); +#endif + void restoreCoreAndJumpTo(); + + // ARM registers + GPRs _registers; + + // We save floating point registers lazily because we can't know ahead of + // time which ones are used. See EHABI #4.7. + + // Whether D0-D15 are saved in the FTSMX instead of FSTMD format. + // + // See EHABI #7.5 that explains how matching instruction sequences for load + // and store need to be used to correctly restore the exact register bits. + bool _use_X_for_vfp_save; + // Whether VFP D0-D15 are saved. + bool _saved_vfp_d0_d15; + // Whether VFPv3 D16-D31 are saved. + bool _saved_vfp_d16_d31; + // VFP registers D0-D15, + padding if saved using FSTMX + unw_fpreg_t _vfp_d0_d15_pad[17]; + // VFPv3 registers D16-D31, always saved using FSTMD + unw_fpreg_t _vfp_d16_d31[16]; +#if defined(__ARM_WMMX) + // Whether iWMMX data registers are saved. + bool _saved_iwmmx; + // Whether iWMMX control registers are saved. + mutable bool _saved_iwmmx_control; + // iWMMX registers + unw_fpreg_t _iwmmx[16]; + // iWMMX control registers + mutable uint32_t _iwmmx_control[4]; +#endif +}; + +inline Registers_arm::Registers_arm(const void *registers) + : _use_X_for_vfp_save(false), + _saved_vfp_d0_d15(false), + _saved_vfp_d16_d31(false) { + static_assert((check_fit::does_fit), + "arm registers do not fit into unw_context_t"); + // See unw_getcontext() note about data. + memcpy(&_registers, registers, sizeof(_registers)); + memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); + memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); +#if defined(__ARM_WMMX) + _saved_iwmmx = false; + _saved_iwmmx_control = false; + memset(&_iwmmx, 0, sizeof(_iwmmx)); + memset(&_iwmmx_control, 0, sizeof(_iwmmx_control)); +#endif +} + +inline Registers_arm::Registers_arm() + : _use_X_for_vfp_save(false), + _saved_vfp_d0_d15(false), + _saved_vfp_d16_d31(false) { + memset(&_registers, 0, sizeof(_registers)); + memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); + memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); +#if defined(__ARM_WMMX) + _saved_iwmmx = false; + _saved_iwmmx_control = false; + memset(&_iwmmx, 0, sizeof(_iwmmx)); + memset(&_iwmmx_control, 0, sizeof(_iwmmx_control)); +#endif +} + +inline bool Registers_arm::validRegister(int regNum) const { + // Returns true for all non-VFP registers supported by the EHABI + // virtual register set (VRS). + if (regNum == UNW_REG_IP) + return true; + + if (regNum == UNW_REG_SP) + return true; + + if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) + return true; + +#if defined(__ARM_WMMX) + if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) + return true; +#endif + + return false; +} + +inline uint32_t Registers_arm::getRegister(int regNum) const { + if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) + return _registers.__sp; + + if (regNum == UNW_ARM_LR) + return _registers.__lr; + + if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) + return _registers.__pc; + + if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) + return _registers.__r[regNum]; + +#if defined(__ARM_WMMX) + if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) { + if (!_saved_iwmmx_control) { + _saved_iwmmx_control = true; + saveiWMMXControl(_iwmmx_control); + } + return _iwmmx_control[regNum - UNW_ARM_WC0]; + } +#endif + + _LIBUNWIND_ABORT("unsupported arm register"); +} + +inline void Registers_arm::setRegister(int regNum, uint32_t value) { + if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) { + _registers.__sp = value; + return; + } + + if (regNum == UNW_ARM_LR) { + _registers.__lr = value; + return; + } + + if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) { + _registers.__pc = value; + return; + } + + if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) { + _registers.__r[regNum] = value; + return; + } + +#if defined(__ARM_WMMX) + if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) { + if (!_saved_iwmmx_control) { + _saved_iwmmx_control = true; + saveiWMMXControl(_iwmmx_control); + } + _iwmmx_control[regNum - UNW_ARM_WC0] = value; + return; + } +#endif + + _LIBUNWIND_ABORT("unsupported arm register"); +} + +inline const char *Registers_arm::getRegisterName(int regNum) { + switch (regNum) { + case UNW_REG_IP: + case UNW_ARM_IP: // UNW_ARM_R15 is alias + return "pc"; + case UNW_ARM_LR: // UNW_ARM_R14 is alias + return "lr"; + case UNW_REG_SP: + case UNW_ARM_SP: // UNW_ARM_R13 is alias + return "sp"; + case UNW_ARM_R0: + return "r0"; + case UNW_ARM_R1: + return "r1"; + case UNW_ARM_R2: + return "r2"; + case UNW_ARM_R3: + return "r3"; + case UNW_ARM_R4: + return "r4"; + case UNW_ARM_R5: + return "r5"; + case UNW_ARM_R6: + return "r6"; + case UNW_ARM_R7: + return "r7"; + case UNW_ARM_R8: + return "r8"; + case UNW_ARM_R9: + return "r9"; + case UNW_ARM_R10: + return "r10"; + case UNW_ARM_R11: + return "r11"; + case UNW_ARM_R12: + return "r12"; + case UNW_ARM_S0: + return "s0"; + case UNW_ARM_S1: + return "s1"; + case UNW_ARM_S2: + return "s2"; + case UNW_ARM_S3: + return "s3"; + case UNW_ARM_S4: + return "s4"; + case UNW_ARM_S5: + return "s5"; + case UNW_ARM_S6: + return "s6"; + case UNW_ARM_S7: + return "s7"; + case UNW_ARM_S8: + return "s8"; + case UNW_ARM_S9: + return "s9"; + case UNW_ARM_S10: + return "s10"; + case UNW_ARM_S11: + return "s11"; + case UNW_ARM_S12: + return "s12"; + case UNW_ARM_S13: + return "s13"; + case UNW_ARM_S14: + return "s14"; + case UNW_ARM_S15: + return "s15"; + case UNW_ARM_S16: + return "s16"; + case UNW_ARM_S17: + return "s17"; + case UNW_ARM_S18: + return "s18"; + case UNW_ARM_S19: + return "s19"; + case UNW_ARM_S20: + return "s20"; + case UNW_ARM_S21: + return "s21"; + case UNW_ARM_S22: + return "s22"; + case UNW_ARM_S23: + return "s23"; + case UNW_ARM_S24: + return "s24"; + case UNW_ARM_S25: + return "s25"; + case UNW_ARM_S26: + return "s26"; + case UNW_ARM_S27: + return "s27"; + case UNW_ARM_S28: + return "s28"; + case UNW_ARM_S29: + return "s29"; + case UNW_ARM_S30: + return "s30"; + case UNW_ARM_S31: + return "s31"; + case UNW_ARM_D0: + return "d0"; + case UNW_ARM_D1: + return "d1"; + case UNW_ARM_D2: + return "d2"; + case UNW_ARM_D3: + return "d3"; + case UNW_ARM_D4: + return "d4"; + case UNW_ARM_D5: + return "d5"; + case UNW_ARM_D6: + return "d6"; + case UNW_ARM_D7: + return "d7"; + case UNW_ARM_D8: + return "d8"; + case UNW_ARM_D9: + return "d9"; + case UNW_ARM_D10: + return "d10"; + case UNW_ARM_D11: + return "d11"; + case UNW_ARM_D12: + return "d12"; + case UNW_ARM_D13: + return "d13"; + case UNW_ARM_D14: + return "d14"; + case UNW_ARM_D15: + return "d15"; + case UNW_ARM_D16: + return "d16"; + case UNW_ARM_D17: + return "d17"; + case UNW_ARM_D18: + return "d18"; + case UNW_ARM_D19: + return "d19"; + case UNW_ARM_D20: + return "d20"; + case UNW_ARM_D21: + return "d21"; + case UNW_ARM_D22: + return "d22"; + case UNW_ARM_D23: + return "d23"; + case UNW_ARM_D24: + return "d24"; + case UNW_ARM_D25: + return "d25"; + case UNW_ARM_D26: + return "d26"; + case UNW_ARM_D27: + return "d27"; + case UNW_ARM_D28: + return "d28"; + case UNW_ARM_D29: + return "d29"; + case UNW_ARM_D30: + return "d30"; + case UNW_ARM_D31: + return "d31"; + default: + return "unknown register"; + } +} + +inline bool Registers_arm::validFloatRegister(int regNum) const { + // NOTE: Consider the intel MMX registers floating points so the + // unw_get_fpreg can be used to transmit the 64-bit data back. + return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31)) +#if defined(__ARM_WMMX) + || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15)) +#endif + ; +} + +inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) { + if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) { + if (!_saved_vfp_d0_d15) { + _saved_vfp_d0_d15 = true; + if (_use_X_for_vfp_save) + saveVFPWithFSTMX(_vfp_d0_d15_pad); + else + saveVFPWithFSTMD(_vfp_d0_d15_pad); + } + return _vfp_d0_d15_pad[regNum - UNW_ARM_D0]; + } + + if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) { + if (!_saved_vfp_d16_d31) { + _saved_vfp_d16_d31 = true; + saveVFPv3(_vfp_d16_d31); + } + return _vfp_d16_d31[regNum - UNW_ARM_D16]; + } + +#if defined(__ARM_WMMX) + if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) { + if (!_saved_iwmmx) { + _saved_iwmmx = true; + saveiWMMX(_iwmmx); + } + return _iwmmx[regNum - UNW_ARM_WR0]; + } +#endif + + _LIBUNWIND_ABORT("Unknown ARM float register"); +} + +inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) { + if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) { + if (!_saved_vfp_d0_d15) { + _saved_vfp_d0_d15 = true; + if (_use_X_for_vfp_save) + saveVFPWithFSTMX(_vfp_d0_d15_pad); + else + saveVFPWithFSTMD(_vfp_d0_d15_pad); + } + _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value; + return; + } + + if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) { + if (!_saved_vfp_d16_d31) { + _saved_vfp_d16_d31 = true; + saveVFPv3(_vfp_d16_d31); + } + _vfp_d16_d31[regNum - UNW_ARM_D16] = value; + return; + } + +#if defined(__ARM_WMMX) + if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) { + if (!_saved_iwmmx) { + _saved_iwmmx = true; + saveiWMMX(_iwmmx); + } + _iwmmx[regNum - UNW_ARM_WR0] = value; + return; + } +#endif + + _LIBUNWIND_ABORT("Unknown ARM float register"); +} + +inline bool Registers_arm::validVectorRegister(int) const { + return false; +} + +inline v128 Registers_arm::getVectorRegister(int) const { + _LIBUNWIND_ABORT("ARM vector support not implemented"); +} + +inline void Registers_arm::setVectorRegister(int, v128) { + _LIBUNWIND_ABORT("ARM vector support not implemented"); +} +#endif // _LIBUNWIND_TARGET_ARM + + +#if defined(_LIBUNWIND_TARGET_OR1K) +/// Registers_or1k holds the register state of a thread in an OpenRISC1000 +/// process. +class _LIBUNWIND_HIDDEN Registers_or1k { +public: + Registers_or1k(); + Registers_or1k(const void *registers); + + bool validRegister(int num) const; + uint32_t getRegister(int num) const; + void setRegister(int num, uint32_t value); + bool validFloatRegister(int num) const; + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int num) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + static const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; } + static int getArch() { return REGISTERS_OR1K; } + + uint64_t getSP() const { return _registers.__r[1]; } + void setSP(uint32_t value) { _registers.__r[1] = value; } + uint64_t getIP() const { return _registers.__pc; } + void setIP(uint32_t value) { _registers.__pc = value; } + +private: + struct or1k_thread_state_t { + unsigned int __r[32]; // r0-r31 + unsigned int __pc; // Program counter + unsigned int __epcr; // Program counter at exception + }; + + or1k_thread_state_t _registers; +}; + +inline Registers_or1k::Registers_or1k(const void *registers) { + static_assert((check_fit::does_fit), + "or1k registers do not fit into unw_context_t"); + memcpy(&_registers, static_cast(registers), + sizeof(_registers)); +} + +inline Registers_or1k::Registers_or1k() { + memset(&_registers, 0, sizeof(_registers)); +} + +inline bool Registers_or1k::validRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return true; + if (regNum == UNW_REG_SP) + return true; + if (regNum < 0) + return false; + if (regNum <= UNW_OR1K_R31) + return true; + if (regNum == UNW_OR1K_EPCR) + return true; + return false; +} + +inline uint32_t Registers_or1k::getRegister(int regNum) const { + if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) + return _registers.__r[regNum - UNW_OR1K_R0]; + + switch (regNum) { + case UNW_REG_IP: + return _registers.__pc; + case UNW_REG_SP: + return _registers.__r[1]; + case UNW_OR1K_EPCR: + return _registers.__epcr; + } + _LIBUNWIND_ABORT("unsupported or1k register"); +} + +inline void Registers_or1k::setRegister(int regNum, uint32_t value) { + if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) { + _registers.__r[regNum - UNW_OR1K_R0] = value; + return; + } + + switch (regNum) { + case UNW_REG_IP: + _registers.__pc = value; + return; + case UNW_REG_SP: + _registers.__r[1] = value; + return; + case UNW_OR1K_EPCR: + _registers.__epcr = value; + return; + } + _LIBUNWIND_ABORT("unsupported or1k register"); +} + +inline bool Registers_or1k::validFloatRegister(int /* regNum */) const { + return false; +} + +inline double Registers_or1k::getFloatRegister(int /* regNum */) const { + _LIBUNWIND_ABORT("or1k float support not implemented"); +} + +inline void Registers_or1k::setFloatRegister(int /* regNum */, + double /* value */) { + _LIBUNWIND_ABORT("or1k float support not implemented"); +} + +inline bool Registers_or1k::validVectorRegister(int /* regNum */) const { + return false; +} + +inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const { + _LIBUNWIND_ABORT("or1k vector support not implemented"); +} + +inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) { + _LIBUNWIND_ABORT("or1k vector support not implemented"); +} + +inline const char *Registers_or1k::getRegisterName(int regNum) { + switch (regNum) { + case UNW_OR1K_R0: + return "r0"; + case UNW_OR1K_R1: + return "r1"; + case UNW_OR1K_R2: + return "r2"; + case UNW_OR1K_R3: + return "r3"; + case UNW_OR1K_R4: + return "r4"; + case UNW_OR1K_R5: + return "r5"; + case UNW_OR1K_R6: + return "r6"; + case UNW_OR1K_R7: + return "r7"; + case UNW_OR1K_R8: + return "r8"; + case UNW_OR1K_R9: + return "r9"; + case UNW_OR1K_R10: + return "r10"; + case UNW_OR1K_R11: + return "r11"; + case UNW_OR1K_R12: + return "r12"; + case UNW_OR1K_R13: + return "r13"; + case UNW_OR1K_R14: + return "r14"; + case UNW_OR1K_R15: + return "r15"; + case UNW_OR1K_R16: + return "r16"; + case UNW_OR1K_R17: + return "r17"; + case UNW_OR1K_R18: + return "r18"; + case UNW_OR1K_R19: + return "r19"; + case UNW_OR1K_R20: + return "r20"; + case UNW_OR1K_R21: + return "r21"; + case UNW_OR1K_R22: + return "r22"; + case UNW_OR1K_R23: + return "r23"; + case UNW_OR1K_R24: + return "r24"; + case UNW_OR1K_R25: + return "r25"; + case UNW_OR1K_R26: + return "r26"; + case UNW_OR1K_R27: + return "r27"; + case UNW_OR1K_R28: + return "r28"; + case UNW_OR1K_R29: + return "r29"; + case UNW_OR1K_R30: + return "r30"; + case UNW_OR1K_R31: + return "r31"; + case UNW_OR1K_EPCR: + return "EPCR"; + default: + return "unknown register"; + } + +} +#endif // _LIBUNWIND_TARGET_OR1K + +#if defined(_LIBUNWIND_TARGET_RISCV) +/// Registers_riscv holds the register state of a thread in a 64-bit RISC-V +/// process. +class _LIBUNWIND_HIDDEN Registers_riscv { +public: + Registers_riscv(); + Registers_riscv(const void *registers); + + bool validRegister(int num) const; + uint64_t getRegister(int num) const; + void setRegister(int num, uint64_t value); + bool validFloatRegister(int num) const; + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int num) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + static const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; } + static int getArch() { return REGISTERS_RISCV; } + + uint64_t getSP() const { return _registers.__x[2]; } + void setSP(uint64_t value) { _registers.__x[2] = value; } + uint64_t getIP() const { return _registers.__x[1]; } + void setIP(uint64_t value) { _registers.__x[1] = value; } + +private: + struct GPRs { + uint64_t __x[32]; // x0-x31 + }; + + GPRs _registers; + double _vectorHalfRegisters[32]; + // Currently only the lower double in 128-bit vectore registers + // is perserved during unwinding. We could define new register + // numbers (> 96) which mean whole vector registers, then this + // struct would need to change to contain whole vector registers. +}; + +inline Registers_riscv::Registers_riscv(const void *registers) { + static_assert((check_fit::does_fit), + "riscv registers do not fit into unw_context_t"); + memcpy(&_registers, registers, sizeof(_registers)); + static_assert(sizeof(GPRs) == 0x100, + "expected VFP registers to be at offset 256"); + memcpy(_vectorHalfRegisters, + static_cast(registers) + sizeof(GPRs), + sizeof(_vectorHalfRegisters)); +} + +inline Registers_riscv::Registers_riscv() { + memset(&_registers, 0, sizeof(_registers)); + memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters)); +} + +inline bool Registers_riscv::validRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return true; + if (regNum == UNW_REG_SP) + return true; + if (regNum < 0) + return false; + if (regNum > 95) + return false; + if ((regNum > 31) && (regNum < 64)) + return false; + return true; +} + +inline uint64_t Registers_riscv::getRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return _registers.__x[1]; + if (regNum == UNW_REG_SP) + return _registers.__x[2]; + if ((regNum >= 0) && (regNum < 32)) + return _registers.__x[regNum]; + _LIBUNWIND_ABORT("unsupported riscv register"); +} + +inline void Registers_riscv::setRegister(int regNum, uint64_t value) { + if (regNum == UNW_REG_IP) + _registers.__x[1] = value; + else if (regNum == UNW_REG_SP) + _registers.__x[2] = value; + else if ((regNum >= 0) && (regNum < 32)) + _registers.__x[regNum] = value; + else + _LIBUNWIND_ABORT("unsupported riscv register"); +} + +inline const char *Registers_riscv::getRegisterName(int regNum) { + switch (regNum) { + case UNW_REG_IP: + return "ra"; + case UNW_REG_SP: + return "sp"; + case UNW_RISCV_X0: + return "x0"; + case UNW_RISCV_X1: + return "ra"; + case UNW_RISCV_X2: + return "sp"; + case UNW_RISCV_X3: + return "x3"; + case UNW_RISCV_X4: + return "x4"; + case UNW_RISCV_X5: + return "x5"; + case UNW_RISCV_X6: + return "x6"; + case UNW_RISCV_X7: + return "x7"; + case UNW_RISCV_X8: + return "x8"; + case UNW_RISCV_X9: + return "x9"; + case UNW_RISCV_X10: + return "x10"; + case UNW_RISCV_X11: + return "x11"; + case UNW_RISCV_X12: + return "x12"; + case UNW_RISCV_X13: + return "x13"; + case UNW_RISCV_X14: + return "x14"; + case UNW_RISCV_X15: + return "x15"; + case UNW_RISCV_X16: + return "x16"; + case UNW_RISCV_X17: + return "x17"; + case UNW_RISCV_X18: + return "x18"; + case UNW_RISCV_X19: + return "x19"; + case UNW_RISCV_X20: + return "x20"; + case UNW_RISCV_X21: + return "x21"; + case UNW_RISCV_X22: + return "x22"; + case UNW_RISCV_X23: + return "x23"; + case UNW_RISCV_X24: + return "x24"; + case UNW_RISCV_X25: + return "x25"; + case UNW_RISCV_X26: + return "x26"; + case UNW_RISCV_X27: + return "x27"; + case UNW_RISCV_X28: + return "x28"; + case UNW_RISCV_X29: + return "x29"; + case UNW_RISCV_X30: + return "x30"; + case UNW_RISCV_X31: + return "x31"; + case UNW_RISCV_D0: + return "d0"; + case UNW_RISCV_D1: + return "d1"; + case UNW_RISCV_D2: + return "d2"; + case UNW_RISCV_D3: + return "d3"; + case UNW_RISCV_D4: + return "d4"; + case UNW_RISCV_D5: + return "d5"; + case UNW_RISCV_D6: + return "d6"; + case UNW_RISCV_D7: + return "d7"; + case UNW_RISCV_D8: + return "d8"; + case UNW_RISCV_D9: + return "d9"; + case UNW_RISCV_D10: + return "d10"; + case UNW_RISCV_D11: + return "d11"; + case UNW_RISCV_D12: + return "d12"; + case UNW_RISCV_D13: + return "d13"; + case UNW_RISCV_D14: + return "d14"; + case UNW_RISCV_D15: + return "d15"; + case UNW_RISCV_D16: + return "d16"; + case UNW_RISCV_D17: + return "d17"; + case UNW_RISCV_D18: + return "d18"; + case UNW_RISCV_D19: + return "d19"; + case UNW_RISCV_D20: + return "d20"; + case UNW_RISCV_D21: + return "d21"; + case UNW_RISCV_D22: + return "d22"; + case UNW_RISCV_D23: + return "d23"; + case UNW_RISCV_D24: + return "d24"; + case UNW_RISCV_D25: + return "d25"; + case UNW_RISCV_D26: + return "d26"; + case UNW_RISCV_D27: + return "d27"; + case UNW_RISCV_D28: + return "d28"; + case UNW_RISCV_D29: + return "d29"; + case UNW_RISCV_D30: + return "d30"; + case UNW_RISCV_D31: + return "d31"; + default: + return "unknown register"; + } +} + +inline bool Registers_riscv::validFloatRegister(int regNum) const { + if (regNum < UNW_RISCV_D0) + return false; + if (regNum > UNW_RISCV_D31) + return false; + return true; +} + +inline double Registers_riscv::getFloatRegister(int regNum) const { + assert(validFloatRegister(regNum)); + return _vectorHalfRegisters[regNum - UNW_RISCV_D0]; +} + +inline void Registers_riscv::setFloatRegister(int regNum, double value) { + assert(validFloatRegister(regNum)); + _vectorHalfRegisters[regNum - UNW_RISCV_D0] = value; +} + +inline bool Registers_riscv::validVectorRegister(int) const { + return false; +} + +inline v128 Registers_riscv::getVectorRegister(int) const { + _LIBUNWIND_ABORT("no riscv vector register support yet"); +} + +inline void Registers_riscv::setVectorRegister(int, v128) { + _LIBUNWIND_ABORT("no riscv vector register support yet"); +} +#endif // _LIBUNWIND_TARGET_RISCV + +#if defined(_LIBUNWIND_TARGET_MIPS_O32) +/// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS +/// process. +class _LIBUNWIND_HIDDEN Registers_mips_o32 { +public: + Registers_mips_o32(); + Registers_mips_o32(const void *registers); + + bool validRegister(int num) const; + uint32_t getRegister(int num) const; + void setRegister(int num, uint32_t value); + bool validFloatRegister(int num) const; + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int num) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + static const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } + static int getArch() { return REGISTERS_MIPS_O32; } + + uint32_t getSP() const { return _registers.__r[29]; } + void setSP(uint32_t value) { _registers.__r[29] = value; } + uint32_t getIP() const { return _registers.__pc; } + void setIP(uint32_t value) { _registers.__pc = value; } + +private: + struct mips_o32_thread_state_t { + uint32_t __r[32]; + uint32_t __pc; + uint32_t __hi; + uint32_t __lo; + }; + + mips_o32_thread_state_t _registers; +#ifdef __mips_hard_float + /// O32 with 32-bit floating point registers only uses half of this + /// space. However, using the same layout for 32-bit vs 64-bit + /// floating point registers results in a single context size for + /// O32 with hard float. + uint32_t _padding; + double _floats[32]; +#endif +}; + +inline Registers_mips_o32::Registers_mips_o32(const void *registers) { + static_assert((check_fit::does_fit), + "mips_o32 registers do not fit into unw_context_t"); + memcpy(&_registers, static_cast(registers), + sizeof(_registers)); +} + +inline Registers_mips_o32::Registers_mips_o32() { + memset(&_registers, 0, sizeof(_registers)); +} + +inline bool Registers_mips_o32::validRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return true; + if (regNum == UNW_REG_SP) + return true; + if (regNum < 0) + return false; + if (regNum <= UNW_MIPS_R31) + return true; +#if __mips_isa_rev != 6 + if (regNum == UNW_MIPS_HI) + return true; + if (regNum == UNW_MIPS_LO) + return true; +#endif +#if defined(__mips_hard_float) && __mips_fpr == 32 + if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) + return true; +#endif + // FIXME: DSP accumulator registers, MSA registers + return false; +} + +inline uint32_t Registers_mips_o32::getRegister(int regNum) const { + if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) + return _registers.__r[regNum - UNW_MIPS_R0]; +#if defined(__mips_hard_float) && __mips_fpr == 32 + if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) { + uint32_t *p; + + if (regNum % 2 == 0) + p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0]; + else + p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1; + return *p; + } +#endif + + switch (regNum) { + case UNW_REG_IP: + return _registers.__pc; + case UNW_REG_SP: + return _registers.__r[29]; + case UNW_MIPS_HI: + return _registers.__hi; + case UNW_MIPS_LO: + return _registers.__lo; + } + _LIBUNWIND_ABORT("unsupported mips_o32 register"); +} + +inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) { + if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) { + _registers.__r[regNum - UNW_MIPS_R0] = value; + return; + } +#if defined(__mips_hard_float) && __mips_fpr == 32 + if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) { + uint32_t *p; + + if (regNum % 2 == 0) + p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0]; + else + p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1; + *p = value; + return; + } +#endif + + switch (regNum) { + case UNW_REG_IP: + _registers.__pc = value; + return; + case UNW_REG_SP: + _registers.__r[29] = value; + return; + case UNW_MIPS_HI: + _registers.__hi = value; + return; + case UNW_MIPS_LO: + _registers.__lo = value; + return; + } + _LIBUNWIND_ABORT("unsupported mips_o32 register"); +} + +inline bool Registers_mips_o32::validFloatRegister(int regNum) const { +#if defined(__mips_hard_float) && __mips_fpr == 64 + if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) + return true; +#endif + return false; +} + +inline double Registers_mips_o32::getFloatRegister(int regNum) const { +#if defined(__mips_hard_float) && __mips_fpr == 64 + assert(validFloatRegister(regNum)); + return _floats[regNum - UNW_MIPS_F0]; +#else + _LIBUNWIND_ABORT("mips_o32 float support not implemented"); +#endif +} + +inline void Registers_mips_o32::setFloatRegister(int regNum, + double value) { +#if defined(__mips_hard_float) && __mips_fpr == 64 + assert(validFloatRegister(regNum)); + _floats[regNum - UNW_MIPS_F0] = value; +#else + _LIBUNWIND_ABORT("mips_o32 float support not implemented"); +#endif +} + +inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const { + return false; +} + +inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const { + _LIBUNWIND_ABORT("mips_o32 vector support not implemented"); +} + +inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) { + _LIBUNWIND_ABORT("mips_o32 vector support not implemented"); +} + +inline const char *Registers_mips_o32::getRegisterName(int regNum) { + switch (regNum) { + case UNW_MIPS_R0: + return "$0"; + case UNW_MIPS_R1: + return "$1"; + case UNW_MIPS_R2: + return "$2"; + case UNW_MIPS_R3: + return "$3"; + case UNW_MIPS_R4: + return "$4"; + case UNW_MIPS_R5: + return "$5"; + case UNW_MIPS_R6: + return "$6"; + case UNW_MIPS_R7: + return "$7"; + case UNW_MIPS_R8: + return "$8"; + case UNW_MIPS_R9: + return "$9"; + case UNW_MIPS_R10: + return "$10"; + case UNW_MIPS_R11: + return "$11"; + case UNW_MIPS_R12: + return "$12"; + case UNW_MIPS_R13: + return "$13"; + case UNW_MIPS_R14: + return "$14"; + case UNW_MIPS_R15: + return "$15"; + case UNW_MIPS_R16: + return "$16"; + case UNW_MIPS_R17: + return "$17"; + case UNW_MIPS_R18: + return "$18"; + case UNW_MIPS_R19: + return "$19"; + case UNW_MIPS_R20: + return "$20"; + case UNW_MIPS_R21: + return "$21"; + case UNW_MIPS_R22: + return "$22"; + case UNW_MIPS_R23: + return "$23"; + case UNW_MIPS_R24: + return "$24"; + case UNW_MIPS_R25: + return "$25"; + case UNW_MIPS_R26: + return "$26"; + case UNW_MIPS_R27: + return "$27"; + case UNW_MIPS_R28: + return "$28"; + case UNW_MIPS_R29: + return "$29"; + case UNW_MIPS_R30: + return "$30"; + case UNW_MIPS_R31: + return "$31"; + case UNW_MIPS_F0: + return "$f0"; + case UNW_MIPS_F1: + return "$f1"; + case UNW_MIPS_F2: + return "$f2"; + case UNW_MIPS_F3: + return "$f3"; + case UNW_MIPS_F4: + return "$f4"; + case UNW_MIPS_F5: + return "$f5"; + case UNW_MIPS_F6: + return "$f6"; + case UNW_MIPS_F7: + return "$f7"; + case UNW_MIPS_F8: + return "$f8"; + case UNW_MIPS_F9: + return "$f9"; + case UNW_MIPS_F10: + return "$f10"; + case UNW_MIPS_F11: + return "$f11"; + case UNW_MIPS_F12: + return "$f12"; + case UNW_MIPS_F13: + return "$f13"; + case UNW_MIPS_F14: + return "$f14"; + case UNW_MIPS_F15: + return "$f15"; + case UNW_MIPS_F16: + return "$f16"; + case UNW_MIPS_F17: + return "$f17"; + case UNW_MIPS_F18: + return "$f18"; + case UNW_MIPS_F19: + return "$f19"; + case UNW_MIPS_F20: + return "$f20"; + case UNW_MIPS_F21: + return "$f21"; + case UNW_MIPS_F22: + return "$f22"; + case UNW_MIPS_F23: + return "$f23"; + case UNW_MIPS_F24: + return "$f24"; + case UNW_MIPS_F25: + return "$f25"; + case UNW_MIPS_F26: + return "$f26"; + case UNW_MIPS_F27: + return "$f27"; + case UNW_MIPS_F28: + return "$f28"; + case UNW_MIPS_F29: + return "$f29"; + case UNW_MIPS_F30: + return "$f30"; + case UNW_MIPS_F31: + return "$f31"; + case UNW_MIPS_HI: + return "$hi"; + case UNW_MIPS_LO: + return "$lo"; + default: + return "unknown register"; + } +} +#endif // _LIBUNWIND_TARGET_MIPS_O32 + +#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) +/// Registers_mips_newabi holds the register state of a thread in a +/// MIPS process using NEWABI (the N32 or N64 ABIs). +class _LIBUNWIND_HIDDEN Registers_mips_newabi { +public: + Registers_mips_newabi(); + Registers_mips_newabi(const void *registers); + + bool validRegister(int num) const; + uint64_t getRegister(int num) const; + void setRegister(int num, uint64_t value); + bool validFloatRegister(int num) const; + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int num) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + static const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } + static int getArch() { return REGISTERS_MIPS_NEWABI; } + + uint64_t getSP() const { return _registers.__r[29]; } + void setSP(uint64_t value) { _registers.__r[29] = value; } + uint64_t getIP() const { return _registers.__pc; } + void setIP(uint64_t value) { _registers.__pc = value; } + +private: + struct mips_newabi_thread_state_t { + uint64_t __r[32]; + uint64_t __pc; + uint64_t __hi; + uint64_t __lo; + }; + + mips_newabi_thread_state_t _registers; +#ifdef __mips_hard_float + double _floats[32]; +#endif +}; + +inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) { + static_assert((check_fit::does_fit), + "mips_newabi registers do not fit into unw_context_t"); + memcpy(&_registers, static_cast(registers), + sizeof(_registers)); +} + +inline Registers_mips_newabi::Registers_mips_newabi() { + memset(&_registers, 0, sizeof(_registers)); +} + +inline bool Registers_mips_newabi::validRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return true; + if (regNum == UNW_REG_SP) + return true; + if (regNum < 0) + return false; + if (regNum <= UNW_MIPS_R31) + return true; +#if __mips_isa_rev != 6 + if (regNum == UNW_MIPS_HI) + return true; + if (regNum == UNW_MIPS_LO) + return true; +#endif + // FIXME: Hard float, DSP accumulator registers, MSA registers + return false; +} + +inline uint64_t Registers_mips_newabi::getRegister(int regNum) const { + if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) + return _registers.__r[regNum - UNW_MIPS_R0]; + + switch (regNum) { + case UNW_REG_IP: + return _registers.__pc; + case UNW_REG_SP: + return _registers.__r[29]; + case UNW_MIPS_HI: + return _registers.__hi; + case UNW_MIPS_LO: + return _registers.__lo; + } + _LIBUNWIND_ABORT("unsupported mips_newabi register"); +} + +inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) { + if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) { + _registers.__r[regNum - UNW_MIPS_R0] = value; + return; + } + + switch (regNum) { + case UNW_REG_IP: + _registers.__pc = value; + return; + case UNW_REG_SP: + _registers.__r[29] = value; + return; + case UNW_MIPS_HI: + _registers.__hi = value; + return; + case UNW_MIPS_LO: + _registers.__lo = value; + return; + } + _LIBUNWIND_ABORT("unsupported mips_newabi register"); +} + +inline bool Registers_mips_newabi::validFloatRegister(int regNum) const { +#ifdef __mips_hard_float + if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) + return true; +#endif + return false; +} + +inline double Registers_mips_newabi::getFloatRegister(int regNum) const { +#ifdef __mips_hard_float + assert(validFloatRegister(regNum)); + return _floats[regNum - UNW_MIPS_F0]; +#else + _LIBUNWIND_ABORT("mips_newabi float support not implemented"); +#endif +} + +inline void Registers_mips_newabi::setFloatRegister(int regNum, + double value) { +#ifdef __mips_hard_float + assert(validFloatRegister(regNum)); + _floats[regNum - UNW_MIPS_F0] = value; +#else + _LIBUNWIND_ABORT("mips_newabi float support not implemented"); +#endif +} + +inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const { + return false; +} + +inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const { + _LIBUNWIND_ABORT("mips_newabi vector support not implemented"); +} + +inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) { + _LIBUNWIND_ABORT("mips_newabi vector support not implemented"); +} + +inline const char *Registers_mips_newabi::getRegisterName(int regNum) { + switch (regNum) { + case UNW_MIPS_R0: + return "$0"; + case UNW_MIPS_R1: + return "$1"; + case UNW_MIPS_R2: + return "$2"; + case UNW_MIPS_R3: + return "$3"; + case UNW_MIPS_R4: + return "$4"; + case UNW_MIPS_R5: + return "$5"; + case UNW_MIPS_R6: + return "$6"; + case UNW_MIPS_R7: + return "$7"; + case UNW_MIPS_R8: + return "$8"; + case UNW_MIPS_R9: + return "$9"; + case UNW_MIPS_R10: + return "$10"; + case UNW_MIPS_R11: + return "$11"; + case UNW_MIPS_R12: + return "$12"; + case UNW_MIPS_R13: + return "$13"; + case UNW_MIPS_R14: + return "$14"; + case UNW_MIPS_R15: + return "$15"; + case UNW_MIPS_R16: + return "$16"; + case UNW_MIPS_R17: + return "$17"; + case UNW_MIPS_R18: + return "$18"; + case UNW_MIPS_R19: + return "$19"; + case UNW_MIPS_R20: + return "$20"; + case UNW_MIPS_R21: + return "$21"; + case UNW_MIPS_R22: + return "$22"; + case UNW_MIPS_R23: + return "$23"; + case UNW_MIPS_R24: + return "$24"; + case UNW_MIPS_R25: + return "$25"; + case UNW_MIPS_R26: + return "$26"; + case UNW_MIPS_R27: + return "$27"; + case UNW_MIPS_R28: + return "$28"; + case UNW_MIPS_R29: + return "$29"; + case UNW_MIPS_R30: + return "$30"; + case UNW_MIPS_R31: + return "$31"; + case UNW_MIPS_F0: + return "$f0"; + case UNW_MIPS_F1: + return "$f1"; + case UNW_MIPS_F2: + return "$f2"; + case UNW_MIPS_F3: + return "$f3"; + case UNW_MIPS_F4: + return "$f4"; + case UNW_MIPS_F5: + return "$f5"; + case UNW_MIPS_F6: + return "$f6"; + case UNW_MIPS_F7: + return "$f7"; + case UNW_MIPS_F8: + return "$f8"; + case UNW_MIPS_F9: + return "$f9"; + case UNW_MIPS_F10: + return "$f10"; + case UNW_MIPS_F11: + return "$f11"; + case UNW_MIPS_F12: + return "$f12"; + case UNW_MIPS_F13: + return "$f13"; + case UNW_MIPS_F14: + return "$f14"; + case UNW_MIPS_F15: + return "$f15"; + case UNW_MIPS_F16: + return "$f16"; + case UNW_MIPS_F17: + return "$f17"; + case UNW_MIPS_F18: + return "$f18"; + case UNW_MIPS_F19: + return "$f19"; + case UNW_MIPS_F20: + return "$f20"; + case UNW_MIPS_F21: + return "$f21"; + case UNW_MIPS_F22: + return "$f22"; + case UNW_MIPS_F23: + return "$f23"; + case UNW_MIPS_F24: + return "$f24"; + case UNW_MIPS_F25: + return "$f25"; + case UNW_MIPS_F26: + return "$f26"; + case UNW_MIPS_F27: + return "$f27"; + case UNW_MIPS_F28: + return "$f28"; + case UNW_MIPS_F29: + return "$f29"; + case UNW_MIPS_F30: + return "$f30"; + case UNW_MIPS_F31: + return "$f31"; + case UNW_MIPS_HI: + return "$hi"; + case UNW_MIPS_LO: + return "$lo"; + default: + return "unknown register"; + } +} +#endif // _LIBUNWIND_TARGET_MIPS_NEWABI + +#if defined(_LIBUNWIND_TARGET_SPARC) +/// Registers_sparc holds the register state of a thread in a 32-bit Sparc +/// process. +class _LIBUNWIND_HIDDEN Registers_sparc { +public: + Registers_sparc(); + Registers_sparc(const void *registers); + + bool validRegister(int num) const; + uint32_t getRegister(int num) const; + void setRegister(int num, uint32_t value); + bool validFloatRegister(int num) const; + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int num) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + static const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC; } + static int getArch() { return REGISTERS_SPARC; } + + uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; } + void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; } + uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; } + void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; } + +private: + struct sparc_thread_state_t { + unsigned int __regs[32]; + }; + + sparc_thread_state_t _registers; +}; + +inline Registers_sparc::Registers_sparc(const void *registers) { + static_assert((check_fit::does_fit), + "sparc registers do not fit into unw_context_t"); + memcpy(&_registers, static_cast(registers), + sizeof(_registers)); +} + +inline Registers_sparc::Registers_sparc() { + memset(&_registers, 0, sizeof(_registers)); +} + +inline bool Registers_sparc::validRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return true; + if (regNum == UNW_REG_SP) + return true; + if (regNum < 0) + return false; + if (regNum <= UNW_SPARC_I7) + return true; + return false; +} + +inline uint32_t Registers_sparc::getRegister(int regNum) const { + if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) { + return _registers.__regs[regNum]; + } + + switch (regNum) { + case UNW_REG_IP: + return _registers.__regs[UNW_SPARC_O7]; + case UNW_REG_SP: + return _registers.__regs[UNW_SPARC_O6]; + } + _LIBUNWIND_ABORT("unsupported sparc register"); +} + +inline void Registers_sparc::setRegister(int regNum, uint32_t value) { + if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) { + _registers.__regs[regNum] = value; + return; + } + + switch (regNum) { + case UNW_REG_IP: + _registers.__regs[UNW_SPARC_O7] = value; + return; + case UNW_REG_SP: + _registers.__regs[UNW_SPARC_O6] = value; + return; + } + _LIBUNWIND_ABORT("unsupported sparc register"); +} + +inline bool Registers_sparc::validFloatRegister(int) const { return false; } + +inline double Registers_sparc::getFloatRegister(int) const { + _LIBUNWIND_ABORT("no Sparc float registers"); +} + +inline void Registers_sparc::setFloatRegister(int, double) { + _LIBUNWIND_ABORT("no Sparc float registers"); +} + +inline bool Registers_sparc::validVectorRegister(int) const { return false; } + +inline v128 Registers_sparc::getVectorRegister(int) const { + _LIBUNWIND_ABORT("no Sparc vector registers"); +} + +inline void Registers_sparc::setVectorRegister(int, v128) { + _LIBUNWIND_ABORT("no Sparc vector registers"); +} + +inline const char *Registers_sparc::getRegisterName(int regNum) { + switch (regNum) { + case UNW_REG_IP: + return "pc"; + case UNW_SPARC_G0: + return "g0"; + case UNW_SPARC_G1: + return "g1"; + case UNW_SPARC_G2: + return "g2"; + case UNW_SPARC_G3: + return "g3"; + case UNW_SPARC_G4: + return "g4"; + case UNW_SPARC_G5: + return "g5"; + case UNW_SPARC_G6: + return "g6"; + case UNW_SPARC_G7: + return "g7"; + case UNW_SPARC_O0: + return "o0"; + case UNW_SPARC_O1: + return "o1"; + case UNW_SPARC_O2: + return "o2"; + case UNW_SPARC_O3: + return "o3"; + case UNW_SPARC_O4: + return "o4"; + case UNW_SPARC_O5: + return "o5"; + case UNW_REG_SP: + case UNW_SPARC_O6: + return "sp"; + case UNW_SPARC_O7: + return "o7"; + case UNW_SPARC_L0: + return "l0"; + case UNW_SPARC_L1: + return "l1"; + case UNW_SPARC_L2: + return "l2"; + case UNW_SPARC_L3: + return "l3"; + case UNW_SPARC_L4: + return "l4"; + case UNW_SPARC_L5: + return "l5"; + case UNW_SPARC_L6: + return "l6"; + case UNW_SPARC_L7: + return "l7"; + case UNW_SPARC_I0: + return "i0"; + case UNW_SPARC_I1: + return "i1"; + case UNW_SPARC_I2: + return "i2"; + case UNW_SPARC_I3: + return "i3"; + case UNW_SPARC_I4: + return "i4"; + case UNW_SPARC_I5: + return "i5"; + case UNW_SPARC_I6: + return "fp"; + case UNW_SPARC_I7: + return "i7"; + default: + return "unknown register"; + } +} +#endif // _LIBUNWIND_TARGET_SPARC + +} // namespace libunwind + +#endif // __REGISTERS_HPP__ Index: head/contrib/libunwind/src/Unwind-EHABI.cpp =================================================================== --- head/contrib/libunwind/src/Unwind-EHABI.cpp (nonexistent) +++ head/contrib/libunwind/src/Unwind-EHABI.cpp (revision 345068) @@ -0,0 +1,991 @@ +//===--------------------------- Unwind-EHABI.cpp -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Implements ARM zero-cost C++ exceptions +// +//===----------------------------------------------------------------------===// + +#include "Unwind-EHABI.h" + +#if defined(_LIBUNWIND_ARM_EHABI) + +#include +#include +#include +#include +#include +#include + +#include + +#include "config.h" +#include "libunwind.h" +#include "libunwind_ext.h" +#include "unwind.h" + +namespace { + +// Strange order: take words in order, but inside word, take from most to least +// signinficant byte. +uint8_t getByte(const uint32_t* data, size_t offset) { + const uint8_t* byteData = reinterpret_cast(data); + return byteData[(offset & ~(size_t)0x03) + (3 - (offset & (size_t)0x03))]; +} + +const char* getNextWord(const char* data, uint32_t* out) { + *out = *reinterpret_cast(data); + return data + 4; +} + +const char* getNextNibble(const char* data, uint32_t* out) { + *out = *reinterpret_cast(data); + return data + 2; +} + +struct Descriptor { + // See # 9.2 + typedef enum { + SU16 = 0, // Short descriptor, 16-bit entries + LU16 = 1, // Long descriptor, 16-bit entries + LU32 = 3, // Long descriptor, 32-bit entries + RESERVED0 = 4, RESERVED1 = 5, RESERVED2 = 6, RESERVED3 = 7, + RESERVED4 = 8, RESERVED5 = 9, RESERVED6 = 10, RESERVED7 = 11, + RESERVED8 = 12, RESERVED9 = 13, RESERVED10 = 14, RESERVED11 = 15 + } Format; + + // See # 9.2 + typedef enum { + CLEANUP = 0x0, + FUNC = 0x1, + CATCH = 0x2, + INVALID = 0x4 + } Kind; +}; + +_Unwind_Reason_Code ProcessDescriptors( + _Unwind_State state, + _Unwind_Control_Block* ucbp, + struct _Unwind_Context* context, + Descriptor::Format format, + const char* descriptorStart, + uint32_t flags) { + + // EHT is inlined in the index using compact form. No descriptors. #5 + if (flags & 0x1) + return _URC_CONTINUE_UNWIND; + + // TODO: We should check the state here, and determine whether we need to + // perform phase1 or phase2 unwinding. + (void)state; + + const char* descriptor = descriptorStart; + uint32_t descriptorWord; + getNextWord(descriptor, &descriptorWord); + while (descriptorWord) { + // Read descriptor based on # 9.2. + uint32_t length; + uint32_t offset; + switch (format) { + case Descriptor::LU32: + descriptor = getNextWord(descriptor, &length); + descriptor = getNextWord(descriptor, &offset); + case Descriptor::LU16: + descriptor = getNextNibble(descriptor, &length); + descriptor = getNextNibble(descriptor, &offset); + default: + assert(false); + return _URC_FAILURE; + } + + // See # 9.2 table for decoding the kind of descriptor. It's a 2-bit value. + Descriptor::Kind kind = + static_cast((length & 0x1) | ((offset & 0x1) << 1)); + + // Clear off flag from last bit. + length &= ~1u; + offset &= ~1u; + uintptr_t scopeStart = ucbp->pr_cache.fnstart + offset; + uintptr_t scopeEnd = scopeStart + length; + uintptr_t pc = _Unwind_GetIP(context); + bool isInScope = (scopeStart <= pc) && (pc < scopeEnd); + + switch (kind) { + case Descriptor::CLEANUP: { + // TODO(ajwong): Handle cleanup descriptors. + break; + } + case Descriptor::FUNC: { + // TODO(ajwong): Handle function descriptors. + break; + } + case Descriptor::CATCH: { + // Catch descriptors require gobbling one more word. + uint32_t landing_pad; + descriptor = getNextWord(descriptor, &landing_pad); + + if (isInScope) { + // TODO(ajwong): This is only phase1 compatible logic. Implement + // phase2. + landing_pad = signExtendPrel31(landing_pad & ~0x80000000); + if (landing_pad == 0xffffffff) { + return _URC_HANDLER_FOUND; + } else if (landing_pad == 0xfffffffe) { + return _URC_FAILURE; + } else { + /* + bool is_reference_type = landing_pad & 0x80000000; + void* matched_object; + if (__cxxabiv1::__cxa_type_match( + ucbp, reinterpret_cast(landing_pad), + is_reference_type, + &matched_object) != __cxxabiv1::ctm_failed) + return _URC_HANDLER_FOUND; + */ + _LIBUNWIND_ABORT("Type matching not implemented"); + } + } + break; + } + default: + _LIBUNWIND_ABORT("Invalid descriptor kind found."); + } + + getNextWord(descriptor, &descriptorWord); + } + + return _URC_CONTINUE_UNWIND; +} + +static _Unwind_Reason_Code unwindOneFrame(_Unwind_State state, + _Unwind_Control_Block* ucbp, + struct _Unwind_Context* context) { + // Read the compact model EHT entry's header # 6.3 + const uint32_t* unwindingData = ucbp->pr_cache.ehtp; + assert((*unwindingData & 0xf0000000) == 0x80000000 && "Must be a compact entry"); + Descriptor::Format format = + static_cast((*unwindingData & 0x0f000000) >> 24); + + const char *lsda = + reinterpret_cast(_Unwind_GetLanguageSpecificData(context)); + + // Handle descriptors before unwinding so they are processed in the context + // of the correct stack frame. + _Unwind_Reason_Code result = + ProcessDescriptors(state, ucbp, context, format, lsda, + ucbp->pr_cache.additional); + + if (result != _URC_CONTINUE_UNWIND) + return result; + + if (unw_step(reinterpret_cast(context)) != UNW_STEP_SUCCESS) + return _URC_FAILURE; + return _URC_CONTINUE_UNWIND; +} + +// Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_CORE / +// _UVRSD_UINT32. +uint32_t RegisterMask(uint8_t start, uint8_t count_minus_one) { + return ((1U << (count_minus_one + 1)) - 1) << start; +} + +// Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_VFP / +// _UVRSD_DOUBLE. +uint32_t RegisterRange(uint8_t start, uint8_t count_minus_one) { + return ((uint32_t)start << 16) | ((uint32_t)count_minus_one + 1); +} + +} // end anonymous namespace + +/** + * Decodes an EHT entry. + * + * @param data Pointer to EHT. + * @param[out] off Offset from return value (in bytes) to begin interpretation. + * @param[out] len Number of bytes in unwind code. + * @return Pointer to beginning of unwind code. + */ +extern "C" const uint32_t* +decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) { + if ((*data & 0x80000000) == 0) { + // 6.2: Generic Model + // + // EHT entry is a prel31 pointing to the PR, followed by data understood + // only by the personality routine. Fortunately, all existing assembler + // implementations, including GNU assembler, LLVM integrated assembler, + // and ARM assembler, assume that the unwind opcodes come after the + // personality rountine address. + *off = 1; // First byte is size data. + *len = (((data[1] >> 24) & 0xff) + 1) * 4; + data++; // Skip the first word, which is the prel31 offset. + } else { + // 6.3: ARM Compact Model + // + // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeded + // by format: + Descriptor::Format format = + static_cast((*data & 0x0f000000) >> 24); + switch (format) { + case Descriptor::SU16: + *len = 4; + *off = 1; + break; + case Descriptor::LU16: + case Descriptor::LU32: + *len = 4 + 4 * ((*data & 0x00ff0000) >> 16); + *off = 2; + break; + default: + return nullptr; + } + } + return data; +} + +_LIBUNWIND_EXPORT _Unwind_Reason_Code +_Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, + size_t offset, size_t len) { + bool wrotePC = false; + bool finish = false; + while (offset < len && !finish) { + uint8_t byte = getByte(data, offset++); + if ((byte & 0x80) == 0) { + uint32_t sp; + _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); + if (byte & 0x40) + sp -= (((uint32_t)byte & 0x3f) << 2) + 4; + else + sp += ((uint32_t)byte << 2) + 4; + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); + } else { + switch (byte & 0xf0) { + case 0x80: { + if (offset >= len) + return _URC_FAILURE; + uint32_t registers = + (((uint32_t)byte & 0x0f) << 12) | + (((uint32_t)getByte(data, offset++)) << 4); + if (!registers) + return _URC_FAILURE; + if (registers & (1 << 15)) + wrotePC = true; + _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32); + break; + } + case 0x90: { + uint8_t reg = byte & 0x0f; + if (reg == 13 || reg == 15) + return _URC_FAILURE; + uint32_t sp; + _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_R0 + reg, + _UVRSD_UINT32, &sp); + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, + &sp); + break; + } + case 0xa0: { + uint32_t registers = RegisterMask(4, byte & 0x07); + if (byte & 0x08) + registers |= 1 << 14; + _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32); + break; + } + case 0xb0: { + switch (byte) { + case 0xb0: + finish = true; + break; + case 0xb1: { + if (offset >= len) + return _URC_FAILURE; + uint8_t registers = getByte(data, offset++); + if (registers & 0xf0 || !registers) + return _URC_FAILURE; + _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32); + break; + } + case 0xb2: { + uint32_t addend = 0; + uint32_t shift = 0; + // This decodes a uleb128 value. + while (true) { + if (offset >= len) + return _URC_FAILURE; + uint32_t v = getByte(data, offset++); + addend |= (v & 0x7f) << shift; + if ((v & 0x80) == 0) + break; + shift += 7; + } + uint32_t sp; + _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, + &sp); + sp += 0x204 + (addend << 2); + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, + &sp); + break; + } + case 0xb3: { + uint8_t v = getByte(data, offset++); + _Unwind_VRS_Pop(context, _UVRSC_VFP, + RegisterRange(static_cast(v >> 4), + v & 0x0f), _UVRSD_VFPX); + break; + } + case 0xb4: + case 0xb5: + case 0xb6: + case 0xb7: + return _URC_FAILURE; + default: + _Unwind_VRS_Pop(context, _UVRSC_VFP, + RegisterRange(8, byte & 0x07), _UVRSD_VFPX); + break; + } + break; + } + case 0xc0: { + switch (byte) { +#if defined(__ARM_WMMX) + case 0xc0: + case 0xc1: + case 0xc2: + case 0xc3: + case 0xc4: + case 0xc5: + _Unwind_VRS_Pop(context, _UVRSC_WMMXD, + RegisterRange(10, byte & 0x7), _UVRSD_DOUBLE); + break; + case 0xc6: { + uint8_t v = getByte(data, offset++); + uint8_t start = static_cast(v >> 4); + uint8_t count_minus_one = v & 0xf; + if (start + count_minus_one >= 16) + return _URC_FAILURE; + _Unwind_VRS_Pop(context, _UVRSC_WMMXD, + RegisterRange(start, count_minus_one), + _UVRSD_DOUBLE); + break; + } + case 0xc7: { + uint8_t v = getByte(data, offset++); + if (!v || v & 0xf0) + return _URC_FAILURE; + _Unwind_VRS_Pop(context, _UVRSC_WMMXC, v, _UVRSD_DOUBLE); + break; + } +#endif + case 0xc8: + case 0xc9: { + uint8_t v = getByte(data, offset++); + uint8_t start = + static_cast(((byte == 0xc8) ? 16 : 0) + (v >> 4)); + uint8_t count_minus_one = v & 0xf; + if (start + count_minus_one >= 32) + return _URC_FAILURE; + _Unwind_VRS_Pop(context, _UVRSC_VFP, + RegisterRange(start, count_minus_one), + _UVRSD_DOUBLE); + break; + } + default: + return _URC_FAILURE; + } + break; + } + case 0xd0: { + if (byte & 0x08) + return _URC_FAILURE; + _Unwind_VRS_Pop(context, _UVRSC_VFP, RegisterRange(8, byte & 0x7), + _UVRSD_DOUBLE); + break; + } + default: + return _URC_FAILURE; + } + } + } + if (!wrotePC) { + uint32_t lr; + _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr); + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr); + } + return _URC_CONTINUE_UNWIND; +} + +extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code +__aeabi_unwind_cpp_pr0(_Unwind_State state, _Unwind_Control_Block *ucbp, + _Unwind_Context *context) { + return unwindOneFrame(state, ucbp, context); +} + +extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code +__aeabi_unwind_cpp_pr1(_Unwind_State state, _Unwind_Control_Block *ucbp, + _Unwind_Context *context) { + return unwindOneFrame(state, ucbp, context); +} + +extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code +__aeabi_unwind_cpp_pr2(_Unwind_State state, _Unwind_Control_Block *ucbp, + _Unwind_Context *context) { + return unwindOneFrame(state, ucbp, context); +} + +static _Unwind_Reason_Code +unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { + // EHABI #7.3 discusses preserving the VRS in a "temporary VRS" during + // phase 1 and then restoring it to the "primary VRS" for phase 2. The + // effect is phase 2 doesn't see any of the VRS manipulations from phase 1. + // In this implementation, the phases don't share the VRS backing store. + // Instead, they are passed the original |uc| and they create a new VRS + // from scratch thus achieving the same effect. + unw_init_local(cursor, uc); + + // Walk each frame looking for a place to stop. + for (bool handlerNotFound = true; handlerNotFound;) { + + // See if frame has code to run (has personality routine). + unw_proc_info_t frameInfo; + if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info " + "failed => _URC_FATAL_PHASE1_ERROR", + static_cast(exception_object)); + return _URC_FATAL_PHASE1_ERROR; + } + + // When tracing, print state information. + if (_LIBUNWIND_TRACING_UNWINDING) { + char functionBuf[512]; + const char *functionName = functionBuf; + unw_word_t offset; + if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), + &offset) != UNW_ESUCCESS) || + (frameInfo.start_ip + offset > frameInfo.end_ip)) + functionName = ".anonymous."; + unw_word_t pc; + unw_get_reg(cursor, UNW_REG_IP, &pc); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR ", func=%s, " + "lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR, + static_cast(exception_object), pc, + frameInfo.start_ip, functionName, + frameInfo.lsda, frameInfo.handler); + } + + // If there is a personality routine, ask it if it will want to stop at + // this frame. + if (frameInfo.handler != 0) { + __personality_routine p = + (__personality_routine)(long)(frameInfo.handler); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): calling personality function %p", + static_cast(exception_object), + reinterpret_cast(reinterpret_cast(p))); + struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor); + exception_object->pr_cache.fnstart = frameInfo.start_ip; + exception_object->pr_cache.ehtp = + (_Unwind_EHT_Header *)frameInfo.unwind_info; + exception_object->pr_cache.additional = frameInfo.flags; + _Unwind_Reason_Code personalityResult = + (*p)(_US_VIRTUAL_UNWIND_FRAME, exception_object, context); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): personality result %d start_ip %x ehtp %p " + "additional %x", + static_cast(exception_object), personalityResult, + exception_object->pr_cache.fnstart, + static_cast(exception_object->pr_cache.ehtp), + exception_object->pr_cache.additional); + switch (personalityResult) { + case _URC_HANDLER_FOUND: + // found a catch clause or locals that need destructing in this frame + // stop search and remember stack pointer at the frame + handlerNotFound = false; + // p should have initialized barrier_cache. EHABI #7.3.5 + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND", + static_cast(exception_object)); + return _URC_NO_REASON; + + case _URC_CONTINUE_UNWIND: + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND", + static_cast(exception_object)); + // continue unwinding + break; + + // EHABI #7.3.3 + case _URC_FAILURE: + return _URC_FAILURE; + + default: + // something went wrong + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR", + static_cast(exception_object)); + return _URC_FATAL_PHASE1_ERROR; + } + } + } + return _URC_NO_REASON; +} + +static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, + _Unwind_Exception *exception_object, + bool resume) { + // See comment at the start of unwind_phase1 regarding VRS integrity. + unw_init_local(cursor, uc); + + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", + static_cast(exception_object)); + int frame_count = 0; + + // Walk each frame until we reach where search phase said to stop. + while (true) { + // Ask libunwind to get next frame (skip over first which is + // _Unwind_RaiseException or _Unwind_Resume). + // + // Resume only ever makes sense for 1 frame. + _Unwind_State state = + resume ? _US_UNWIND_FRAME_RESUME : _US_UNWIND_FRAME_STARTING; + if (resume && frame_count == 1) { + // On a resume, first unwind the _Unwind_Resume() frame. The next frame + // is now the landing pad for the cleanup from a previous execution of + // phase2. To continue unwindingly correctly, replace VRS[15] with the + // IP of the frame that the previous run of phase2 installed the context + // for. After this, continue unwinding as if normal. + // + // See #7.4.6 for details. + unw_set_reg(cursor, UNW_REG_IP, + exception_object->unwinder_cache.reserved2); + resume = false; + } + + // Get info about this frame. + unw_word_t sp; + unw_proc_info_t frameInfo; + unw_get_reg(cursor, UNW_REG_SP, &sp); + if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info " + "failed => _URC_FATAL_PHASE2_ERROR", + static_cast(exception_object)); + return _URC_FATAL_PHASE2_ERROR; + } + + // When tracing, print state information. + if (_LIBUNWIND_TRACING_UNWINDING) { + char functionBuf[512]; + const char *functionName = functionBuf; + unw_word_t offset; + if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), + &offset) != UNW_ESUCCESS) || + (frameInfo.start_ip + offset > frameInfo.end_ip)) + functionName = ".anonymous."; + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR ", func=%s, sp=0x%" PRIxPTR ", " + "lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "", + static_cast(exception_object), frameInfo.start_ip, + functionName, sp, frameInfo.lsda, + frameInfo.handler); + } + + // If there is a personality routine, tell it we are unwinding. + if (frameInfo.handler != 0) { + __personality_routine p = + (__personality_routine)(long)(frameInfo.handler); + struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor); + // EHABI #7.2 + exception_object->pr_cache.fnstart = frameInfo.start_ip; + exception_object->pr_cache.ehtp = + (_Unwind_EHT_Header *)frameInfo.unwind_info; + exception_object->pr_cache.additional = frameInfo.flags; + _Unwind_Reason_Code personalityResult = + (*p)(state, exception_object, context); + switch (personalityResult) { + case _URC_CONTINUE_UNWIND: + // Continue unwinding + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND", + static_cast(exception_object)); + // EHABI #7.2 + if (sp == exception_object->barrier_cache.sp) { + // Phase 1 said we would stop at this frame, but we did not... + _LIBUNWIND_ABORT("during phase1 personality function said it would " + "stop here, but now in phase2 it did not stop here"); + } + break; + case _URC_INSTALL_CONTEXT: + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT", + static_cast(exception_object)); + // Personality routine says to transfer control to landing pad. + // We may get control back if landing pad calls _Unwind_Resume(). + if (_LIBUNWIND_TRACING_UNWINDING) { + unw_word_t pc; + unw_get_reg(cursor, UNW_REG_IP, &pc); + unw_get_reg(cursor, UNW_REG_SP, &sp); + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " + "user code with ip=0x%" PRIxPTR ", sp=0x%" PRIxPTR, + static_cast(exception_object), + pc, sp); + } + + { + // EHABI #7.4.1 says we need to preserve pc for when _Unwind_Resume + // is called back, to find this same frame. + unw_word_t pc; + unw_get_reg(cursor, UNW_REG_IP, &pc); + exception_object->unwinder_cache.reserved2 = (uint32_t)pc; + } + unw_resume(cursor); + // unw_resume() only returns if there was an error. + return _URC_FATAL_PHASE2_ERROR; + + // # EHABI #7.4.3 + case _URC_FAILURE: + abort(); + + default: + // Personality routine returned an unknown result code. + _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", + personalityResult); + return _URC_FATAL_PHASE2_ERROR; + } + } + frame_count++; + } + + // Clean up phase did not resume at the frame that the search phase + // said it would... + return _URC_FATAL_PHASE2_ERROR; +} + +/// Called by __cxa_throw. Only returns if there is a fatal error. +_LIBUNWIND_EXPORT _Unwind_Reason_Code +_Unwind_RaiseException(_Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)", + static_cast(exception_object)); + unw_context_t uc; + unw_cursor_t cursor; + unw_getcontext(&uc); + + // This field for is for compatibility with GCC to say this isn't a forced + // unwind. EHABI #7.2 + exception_object->unwinder_cache.reserved1 = 0; + + // phase 1: the search phase + _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object); + if (phase1 != _URC_NO_REASON) + return phase1; + + // phase 2: the clean up phase + return unwind_phase2(&uc, &cursor, exception_object, false); +} + +_LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) { + // This is to be called when exception handling completes to give us a chance + // to perform any housekeeping. EHABI #7.2. But we have nothing to do here. + (void)exception_object; +} + +/// When _Unwind_RaiseException() is in phase2, it hands control +/// to the personality function at each frame. The personality +/// may force a jump to a landing pad in that function, the landing +/// pad code may then call _Unwind_Resume() to continue with the +/// unwinding. Note: the call to _Unwind_Resume() is from compiler +/// geneated user code. All other _Unwind_* routines are called +/// by the C++ runtime __cxa_* routines. +/// +/// Note: re-throwing an exception (as opposed to continuing the unwind) +/// is implemented by having the code call __cxa_rethrow() which +/// in turn calls _Unwind_Resume_or_Rethrow(). +_LIBUNWIND_EXPORT void +_Unwind_Resume(_Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", + static_cast(exception_object)); + unw_context_t uc; + unw_cursor_t cursor; + unw_getcontext(&uc); + + // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0, + // which is in the same position as private_1 below. + // TODO(ajwong): Who wronte the above? Why is it true? + unwind_phase2(&uc, &cursor, exception_object, true); + + // Clients assume _Unwind_Resume() does not return, so all we can do is abort. + _LIBUNWIND_ABORT("_Unwind_Resume() can't return"); +} + +/// Called by personality handler during phase 2 to get LSDA for current frame. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { + unw_cursor_t *cursor = (unw_cursor_t *)context; + unw_proc_info_t frameInfo; + uintptr_t result = 0; + if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) + result = (uintptr_t)frameInfo.lsda; + _LIBUNWIND_TRACE_API( + "_Unwind_GetLanguageSpecificData(context=%p) => 0x%llx", + static_cast(context), (long long)result); + return result; +} + +static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation, + void* valuep) { + uint64_t value = 0; + switch (representation) { + case _UVRSD_UINT32: + case _UVRSD_FLOAT: + memcpy(&value, valuep, sizeof(uint32_t)); + break; + + case _UVRSD_VFPX: + case _UVRSD_UINT64: + case _UVRSD_DOUBLE: + memcpy(&value, valuep, sizeof(uint64_t)); + break; + } + return value; +} + +_LIBUNWIND_EXPORT _Unwind_VRS_Result +_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, + uint32_t regno, _Unwind_VRS_DataRepresentation representation, + void *valuep) { + _LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, " + "rep=%d, value=0x%llX)", + static_cast(context), regclass, regno, + representation, + ValueAsBitPattern(representation, valuep)); + unw_cursor_t *cursor = (unw_cursor_t *)context; + switch (regclass) { + case _UVRSC_CORE: + if (representation != _UVRSD_UINT32 || regno > 15) + return _UVRSR_FAILED; + return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno), + *(unw_word_t *)valuep) == UNW_ESUCCESS + ? _UVRSR_OK + : _UVRSR_FAILED; + case _UVRSC_VFP: + if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE) + return _UVRSR_FAILED; + if (representation == _UVRSD_VFPX) { + // Can only touch d0-15 with FSTMFDX. + if (regno > 15) + return _UVRSR_FAILED; + unw_save_vfp_as_X(cursor); + } else { + if (regno > 31) + return _UVRSR_FAILED; + } + return unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno), + *(unw_fpreg_t *)valuep) == UNW_ESUCCESS + ? _UVRSR_OK + : _UVRSR_FAILED; +#if defined(__ARM_WMMX) + case _UVRSC_WMMXC: + if (representation != _UVRSD_UINT32 || regno > 3) + return _UVRSR_FAILED; + return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno), + *(unw_word_t *)valuep) == UNW_ESUCCESS + ? _UVRSR_OK + : _UVRSR_FAILED; + case _UVRSC_WMMXD: + if (representation != _UVRSD_DOUBLE || regno > 31) + return _UVRSR_FAILED; + return unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno), + *(unw_fpreg_t *)valuep) == UNW_ESUCCESS + ? _UVRSR_OK + : _UVRSR_FAILED; +#else + case _UVRSC_WMMXC: + case _UVRSC_WMMXD: + break; +#endif + } + _LIBUNWIND_ABORT("unsupported register class"); +} + +static _Unwind_VRS_Result +_Unwind_VRS_Get_Internal(_Unwind_Context *context, + _Unwind_VRS_RegClass regclass, uint32_t regno, + _Unwind_VRS_DataRepresentation representation, + void *valuep) { + unw_cursor_t *cursor = (unw_cursor_t *)context; + switch (regclass) { + case _UVRSC_CORE: + if (representation != _UVRSD_UINT32 || regno > 15) + return _UVRSR_FAILED; + return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno), + (unw_word_t *)valuep) == UNW_ESUCCESS + ? _UVRSR_OK + : _UVRSR_FAILED; + case _UVRSC_VFP: + if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE) + return _UVRSR_FAILED; + if (representation == _UVRSD_VFPX) { + // Can only touch d0-15 with FSTMFDX. + if (regno > 15) + return _UVRSR_FAILED; + unw_save_vfp_as_X(cursor); + } else { + if (regno > 31) + return _UVRSR_FAILED; + } + return unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno), + (unw_fpreg_t *)valuep) == UNW_ESUCCESS + ? _UVRSR_OK + : _UVRSR_FAILED; +#if defined(__ARM_WMMX) + case _UVRSC_WMMXC: + if (representation != _UVRSD_UINT32 || regno > 3) + return _UVRSR_FAILED; + return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno), + (unw_word_t *)valuep) == UNW_ESUCCESS + ? _UVRSR_OK + : _UVRSR_FAILED; + case _UVRSC_WMMXD: + if (representation != _UVRSD_DOUBLE || regno > 31) + return _UVRSR_FAILED; + return unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno), + (unw_fpreg_t *)valuep) == UNW_ESUCCESS + ? _UVRSR_OK + : _UVRSR_FAILED; +#else + case _UVRSC_WMMXC: + case _UVRSC_WMMXD: + break; +#endif + } + _LIBUNWIND_ABORT("unsupported register class"); +} + +_LIBUNWIND_EXPORT _Unwind_VRS_Result +_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, + uint32_t regno, _Unwind_VRS_DataRepresentation representation, + void *valuep) { + _Unwind_VRS_Result result = + _Unwind_VRS_Get_Internal(context, regclass, regno, representation, + valuep); + _LIBUNWIND_TRACE_API("_Unwind_VRS_Get(context=%p, regclass=%d, reg=%d, " + "rep=%d, value=0x%llX, result = %d)", + static_cast(context), regclass, regno, + representation, + ValueAsBitPattern(representation, valuep), result); + return result; +} + +_Unwind_VRS_Result +_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, + uint32_t discriminator, + _Unwind_VRS_DataRepresentation representation) { + _LIBUNWIND_TRACE_API("_Unwind_VRS_Pop(context=%p, regclass=%d, " + "discriminator=%d, representation=%d)", + static_cast(context), regclass, discriminator, + representation); + switch (regclass) { + case _UVRSC_WMMXC: +#if !defined(__ARM_WMMX) + break; +#endif + case _UVRSC_CORE: { + if (representation != _UVRSD_UINT32) + return _UVRSR_FAILED; + // When popping SP from the stack, we don't want to override it from the + // computed new stack location. See EHABI #7.5.4 table 3. + bool poppedSP = false; + uint32_t* sp; + if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, + _UVRSD_UINT32, &sp) != _UVRSR_OK) { + return _UVRSR_FAILED; + } + for (uint32_t i = 0; i < 16; ++i) { + if (!(discriminator & static_cast(1 << i))) + continue; + uint32_t value = *sp++; + if (regclass == _UVRSC_CORE && i == 13) + poppedSP = true; + if (_Unwind_VRS_Set(context, regclass, i, + _UVRSD_UINT32, &value) != _UVRSR_OK) { + return _UVRSR_FAILED; + } + } + if (!poppedSP) { + return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, + _UVRSD_UINT32, &sp); + } + return _UVRSR_OK; + } + case _UVRSC_WMMXD: +#if !defined(__ARM_WMMX) + break; +#endif + case _UVRSC_VFP: { + if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE) + return _UVRSR_FAILED; + uint32_t first = discriminator >> 16; + uint32_t count = discriminator & 0xffff; + uint32_t end = first+count; + uint32_t* sp; + if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, + _UVRSD_UINT32, &sp) != _UVRSR_OK) { + return _UVRSR_FAILED; + } + // For _UVRSD_VFPX, we're assuming the data is stored in FSTMX "standard + // format 1", which is equivalent to FSTMD + a padding word. + for (uint32_t i = first; i < end; ++i) { + // SP is only 32-bit aligned so don't copy 64-bit at a time. + uint64_t value = *sp++; + value |= ((uint64_t)(*sp++)) << 32; + if (_Unwind_VRS_Set(context, regclass, i, representation, &value) != + _UVRSR_OK) + return _UVRSR_FAILED; + } + if (representation == _UVRSD_VFPX) + ++sp; + return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, + &sp); + } + } + _LIBUNWIND_ABORT("unsupported register class"); +} + +/// Called by personality handler during phase 2 to find the start of the +/// function. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetRegionStart(struct _Unwind_Context *context) { + unw_cursor_t *cursor = (unw_cursor_t *)context; + unw_proc_info_t frameInfo; + uintptr_t result = 0; + if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) + result = (uintptr_t)frameInfo.start_ip; + _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%llX", + static_cast(context), (long long)result); + return result; +} + + +/// Called by personality handler during phase 2 if a foreign exception +// is caught. +_LIBUNWIND_EXPORT void +_Unwind_DeleteException(_Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)", + static_cast(exception_object)); + if (exception_object->exception_cleanup != NULL) + (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, + exception_object); +} + +extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code +__gnu_unwind_frame(_Unwind_Exception *exception_object, + struct _Unwind_Context *context) { + unw_cursor_t *cursor = (unw_cursor_t *)context; + if (unw_step(cursor) != UNW_STEP_SUCCESS) + return _URC_FAILURE; + return _URC_OK; +} + +#endif // defined(_LIBUNWIND_ARM_EHABI) Property changes on: head/contrib/libunwind/src/Unwind-EHABI.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/Unwind-EHABI.h =================================================================== --- head/contrib/libunwind/src/Unwind-EHABI.h (nonexistent) +++ head/contrib/libunwind/src/Unwind-EHABI.h (revision 345068) @@ -0,0 +1,51 @@ +//===------------------------- Unwind-EHABI.hpp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +//===----------------------------------------------------------------------===// + +#ifndef __UNWIND_EHABI_H__ +#define __UNWIND_EHABI_H__ + +#include <__libunwind_config.h> + +#if defined(_LIBUNWIND_ARM_EHABI) + +#include +#include + +// Unable to unwind in the ARM index table (section 5 EHABI). +#define UNW_EXIDX_CANTUNWIND 0x1 + +static inline uint32_t signExtendPrel31(uint32_t data) { + return data | ((data & 0x40000000u) << 1); +} + +static inline uint32_t readPrel31(const uint32_t *data) { + return (((uint32_t)(uintptr_t)data) + signExtendPrel31(*data)); +} + +#if defined(__cplusplus) +extern "C" { +#endif + +extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr0( + _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); + +extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr1( + _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); + +extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr2( + _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // defined(_LIBUNWIND_ARM_EHABI) + +#endif // __UNWIND_EHABI_H__ Property changes on: head/contrib/libunwind/src/Unwind-EHABI.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/Unwind-seh.cpp =================================================================== --- head/contrib/libunwind/src/Unwind-seh.cpp (nonexistent) +++ head/contrib/libunwind/src/Unwind-seh.cpp (revision 345068) @@ -0,0 +1,491 @@ +//===--------------------------- Unwind-seh.cpp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements SEH-based Itanium C++ exceptions. +// +//===----------------------------------------------------------------------===// + +#include "config.h" + +#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "libunwind_ext.h" +#include "UnwindCursor.hpp" + +using namespace libunwind; + +#define STATUS_USER_DEFINED (1u << 29) + +#define STATUS_GCC_MAGIC (('G' << 16) | ('C' << 8) | 'C') + +#define MAKE_CUSTOM_STATUS(s, c) \ + ((NTSTATUS)(((s) << 30) | STATUS_USER_DEFINED | (c))) +#define MAKE_GCC_EXCEPTION(c) \ + MAKE_CUSTOM_STATUS(STATUS_SEVERITY_SUCCESS, STATUS_GCC_MAGIC | ((c) << 24)) + +/// SEH exception raised by libunwind when the program calls +/// \c _Unwind_RaiseException. +#define STATUS_GCC_THROW MAKE_GCC_EXCEPTION(0) // 0x20474343 +/// SEH exception raised by libunwind to initiate phase 2 of exception +/// handling. +#define STATUS_GCC_UNWIND MAKE_GCC_EXCEPTION(1) // 0x21474343 + +/// Class of foreign exceptions based on unrecognized SEH exceptions. +static const uint64_t kSEHExceptionClass = 0x434C4E4753454800; // CLNGSEH\0 + +/// Exception cleanup routine used by \c _GCC_specific_handler to +/// free foreign exceptions. +static void seh_exc_cleanup(_Unwind_Reason_Code urc, _Unwind_Exception *exc) { + if (exc->exception_class != kSEHExceptionClass) + _LIBUNWIND_ABORT("SEH cleanup called on non-SEH exception"); + free(exc); +} + +static int _unw_init_seh(unw_cursor_t *cursor, CONTEXT *ctx); +static DISPATCHER_CONTEXT *_unw_seh_get_disp_ctx(unw_cursor_t *cursor); +static void _unw_seh_set_disp_ctx(unw_cursor_t *cursor, DISPATCHER_CONTEXT *disp); + +/// Common implementation of SEH-style handler functions used by Itanium- +/// style frames. Depending on how and why it was called, it may do one of: +/// a) Delegate to the given Itanium-style personality function; or +/// b) Initiate a collided unwind to halt unwinding. +_LIBUNWIND_EXPORT EXCEPTION_DISPOSITION +_GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, + DISPATCHER_CONTEXT *disp, __personality_routine pers) { + unw_context_t uc; + unw_cursor_t cursor; + _Unwind_Exception *exc; + _Unwind_Action action; + struct _Unwind_Context *ctx = nullptr; + _Unwind_Reason_Code urc; + uintptr_t retval, target; + bool ours = false; + + _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler(%#010x(%x), %p)", ms_exc->ExceptionCode, ms_exc->ExceptionFlags, frame); + if (ms_exc->ExceptionCode == STATUS_GCC_UNWIND) { + if (IS_TARGET_UNWIND(ms_exc->ExceptionFlags)) { + // Set up the upper return value (the lower one and the target PC + // were set in the call to RtlUnwindEx()) for the landing pad. +#ifdef __x86_64__ + disp->ContextRecord->Rdx = ms_exc->ExceptionInformation[3]; +#elif defined(__arm__) + disp->ContextRecord->R1 = ms_exc->ExceptionInformation[3]; +#elif defined(__aarch64__) + disp->ContextRecord->X1 = ms_exc->ExceptionInformation[3]; +#endif + } + // This is the collided unwind to the landing pad. Nothing to do. + return ExceptionContinueSearch; + } + + if (ms_exc->ExceptionCode == STATUS_GCC_THROW) { + // This is (probably) a libunwind-controlled exception/unwind. Recover the + // parameters which we set below, and pass them to the personality function. + ours = true; + exc = (_Unwind_Exception *)ms_exc->ExceptionInformation[0]; + if (!IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) { + ctx = (struct _Unwind_Context *)ms_exc->ExceptionInformation[1]; + action = (_Unwind_Action)ms_exc->ExceptionInformation[2]; + } + } else { + // Foreign exception. + exc = (_Unwind_Exception *)malloc(sizeof(_Unwind_Exception)); + exc->exception_class = kSEHExceptionClass; + exc->exception_cleanup = seh_exc_cleanup; + memset(exc->private_, 0, sizeof(exc->private_)); + } + if (!ctx) { + _unw_init_seh(&cursor, disp->ContextRecord); + _unw_seh_set_disp_ctx(&cursor, disp); + unw_set_reg(&cursor, UNW_REG_IP, disp->ControlPc-1); + ctx = (struct _Unwind_Context *)&cursor; + + if (!IS_UNWINDING(ms_exc->ExceptionFlags)) { + if (ours && ms_exc->NumberParameters > 1) + action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_FORCE_UNWIND); + else + action = _UA_SEARCH_PHASE; + } else { + if (ours && ms_exc->ExceptionInformation[1] == (ULONG_PTR)frame) + action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME); + else + action = _UA_CLEANUP_PHASE; + } + } + + _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() calling personality function %p(1, %d, %llx, %p, %p)", pers, action, exc->exception_class, exc, ctx); + urc = pers(1, action, exc->exception_class, exc, ctx); + _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() personality returned %d", urc); + switch (urc) { + case _URC_CONTINUE_UNWIND: + // If we're in phase 2, and the personality routine said to continue + // at the target frame, we're in real trouble. + if (action & _UA_HANDLER_FRAME) + _LIBUNWIND_ABORT("Personality continued unwind at the target frame!"); + return ExceptionContinueSearch; + case _URC_HANDLER_FOUND: + // If we were called by __libunwind_seh_personality(), indicate that + // a handler was found; otherwise, initiate phase 2 by unwinding. + if (ours && ms_exc->NumberParameters > 1) + return 4 /* ExecptionExecuteHandler in mingw */; + // This should never happen in phase 2. + if (IS_UNWINDING(ms_exc->ExceptionFlags)) + _LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!"); + exc->private_[1] = (ULONG_PTR)frame; + if (ours) { + ms_exc->NumberParameters = 4; + ms_exc->ExceptionInformation[1] = (ULONG_PTR)frame; + } + // FIXME: Indicate target frame in foreign case! + // phase 2: the clean up phase + RtlUnwindEx(frame, (PVOID)disp->ControlPc, ms_exc, exc, ms_ctx, disp->HistoryTable); + _LIBUNWIND_ABORT("RtlUnwindEx() failed"); + case _URC_INSTALL_CONTEXT: { + // If we were called by __libunwind_seh_personality(), indicate that + // a handler was found; otherwise, it's time to initiate a collided + // unwind to the target. + if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) + return 4 /* ExecptionExecuteHandler in mingw */; + // This should never happen in phase 1. + if (!IS_UNWINDING(ms_exc->ExceptionFlags)) + _LIBUNWIND_ABORT("Personality installed context during phase 1!"); +#ifdef __x86_64__ + exc->private_[2] = disp->TargetIp; + unw_get_reg(&cursor, UNW_X86_64_RAX, &retval); + unw_get_reg(&cursor, UNW_X86_64_RDX, &exc->private_[3]); +#elif defined(__arm__) + exc->private_[2] = disp->TargetPc; + unw_get_reg(&cursor, UNW_ARM_R0, &retval); + unw_get_reg(&cursor, UNW_ARM_R1, &exc->private_[3]); +#elif defined(__aarch64__) + exc->private_[2] = disp->TargetPc; + unw_get_reg(&cursor, UNW_ARM64_X0, &retval); + unw_get_reg(&cursor, UNW_ARM64_X1, &exc->private_[3]); +#endif + unw_get_reg(&cursor, UNW_REG_IP, &target); + ms_exc->ExceptionCode = STATUS_GCC_UNWIND; +#ifdef __x86_64__ + ms_exc->ExceptionInformation[2] = disp->TargetIp; +#elif defined(__arm__) || defined(__aarch64__) + ms_exc->ExceptionInformation[2] = disp->TargetPc; +#endif + ms_exc->ExceptionInformation[3] = exc->private_[3]; + // Give NTRTL some scratch space to keep track of the collided unwind. + // Don't use the one that was passed in; we don't want to overwrite the + // context in the DISPATCHER_CONTEXT. + CONTEXT new_ctx; + RtlUnwindEx(frame, (PVOID)target, ms_exc, (PVOID)retval, &new_ctx, disp->HistoryTable); + _LIBUNWIND_ABORT("RtlUnwindEx() failed"); + } + // Anything else indicates a serious problem. + default: return ExceptionContinueExecution; + } +} + +/// Personality function returned by \c unw_get_proc_info() in SEH contexts. +/// This is a wrapper that calls the real SEH handler function, which in +/// turn (at least, for Itanium-style frames) calls the real Itanium +/// personality function (see \c _GCC_specific_handler()). +extern "C" _Unwind_Reason_Code +__libunwind_seh_personality(int version, _Unwind_Action state, + uint64_t klass, _Unwind_Exception *exc, + struct _Unwind_Context *context) { + EXCEPTION_RECORD ms_exc; + bool phase2 = (state & (_UA_SEARCH_PHASE|_UA_CLEANUP_PHASE)) == _UA_CLEANUP_PHASE; + ms_exc.ExceptionCode = STATUS_GCC_THROW; + ms_exc.ExceptionFlags = 0; + ms_exc.NumberParameters = 3; + ms_exc.ExceptionInformation[0] = (ULONG_PTR)exc; + ms_exc.ExceptionInformation[1] = (ULONG_PTR)context; + ms_exc.ExceptionInformation[2] = state; + DISPATCHER_CONTEXT *disp_ctx = _unw_seh_get_disp_ctx((unw_cursor_t *)context); + EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc, + (PVOID)disp_ctx->EstablisherFrame, + disp_ctx->ContextRecord, + disp_ctx); + switch (ms_act) { + case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND; + case 4 /*ExceptionExecuteHandler*/: + return phase2 ? _URC_INSTALL_CONTEXT : _URC_HANDLER_FOUND; + default: + return phase2 ? _URC_FATAL_PHASE2_ERROR : _URC_FATAL_PHASE1_ERROR; + } +} + +static _Unwind_Reason_Code +unwind_phase2_forced(unw_context_t *uc, + _Unwind_Exception *exception_object, + _Unwind_Stop_Fn stop, void *stop_parameter) { + unw_cursor_t cursor2; + unw_init_local(&cursor2, uc); + + // Walk each frame until we reach where search phase said to stop + while (unw_step(&cursor2) > 0) { + + // Update info about this frame. + unw_proc_info_t frameInfo; + if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step " + "failed => _URC_END_OF_STACK", + (void *)exception_object); + return _URC_FATAL_PHASE2_ERROR; + } + + // When tracing, print state information. + if (_LIBUNWIND_TRACING_UNWINDING) { + char functionBuf[512]; + const char *functionName = functionBuf; + unw_word_t offset; + if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf), + &offset) != UNW_ESUCCESS) || + (frameInfo.start_ip + offset > frameInfo.end_ip)) + functionName = ".anonymous."; + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64 + ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64, + (void *)exception_object, frameInfo.start_ip, functionName, + frameInfo.lsda, frameInfo.handler); + } + + // Call stop function at each frame. + _Unwind_Action action = + (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); + _Unwind_Reason_Code stopResult = + (*stop)(1, action, exception_object->exception_class, exception_object, + (struct _Unwind_Context *)(&cursor2), stop_parameter); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): stop function returned %d", + (void *)exception_object, stopResult); + if (stopResult != _URC_NO_REASON) { + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): stopped by stop function", + (void *)exception_object); + return _URC_FATAL_PHASE2_ERROR; + } + + // If there is a personality routine, tell it we are unwinding. + if (frameInfo.handler != 0) { + __personality_routine p = + (__personality_routine)(intptr_t)(frameInfo.handler); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", + (void *)exception_object, (void *)(uintptr_t)p); + _Unwind_Reason_Code personalityResult = + (*p)(1, action, exception_object->exception_class, exception_object, + (struct _Unwind_Context *)(&cursor2)); + switch (personalityResult) { + case _URC_CONTINUE_UNWIND: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned " + "_URC_CONTINUE_UNWIND", + (void *)exception_object); + // Destructors called, continue unwinding + break; + case _URC_INSTALL_CONTEXT: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned " + "_URC_INSTALL_CONTEXT", + (void *)exception_object); + // We may get control back if landing pad calls _Unwind_Resume(). + unw_resume(&cursor2); + break; + default: + // Personality routine returned an unknown result code. + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned %d, " + "_URC_FATAL_PHASE2_ERROR", + (void *)exception_object, personalityResult); + return _URC_FATAL_PHASE2_ERROR; + } + } + } + + // Call stop function one last time and tell it we've reached the end + // of the stack. + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " + "function with _UA_END_OF_STACK", + (void *)exception_object); + _Unwind_Action lastAction = + (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); + (*stop)(1, lastAction, exception_object->exception_class, exception_object, + (struct _Unwind_Context *)(&cursor2), stop_parameter); + + // Clean up phase did not resume at the frame that the search phase said it + // would. + return _URC_FATAL_PHASE2_ERROR; +} + +/// Called by \c __cxa_throw(). Only returns if there is a fatal error. +_LIBUNWIND_EXPORT _Unwind_Reason_Code +_Unwind_RaiseException(_Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)", + (void *)exception_object); + + // Mark that this is a non-forced unwind, so _Unwind_Resume() + // can do the right thing. + memset(exception_object->private_, 0, sizeof(exception_object->private_)); + + // phase 1: the search phase + // We'll let the system do that for us. + RaiseException(STATUS_GCC_THROW, 0, 1, (ULONG_PTR *)&exception_object); + + // If we get here, either something went horribly wrong or we reached the + // top of the stack. Either way, let libc++abi call std::terminate(). + return _URC_END_OF_STACK; +} + +/// When \c _Unwind_RaiseException() is in phase2, it hands control +/// to the personality function at each frame. The personality +/// may force a jump to a landing pad in that function; the landing +/// pad code may then call \c _Unwind_Resume() to continue with the +/// unwinding. Note: the call to \c _Unwind_Resume() is from compiler +/// geneated user code. All other \c _Unwind_* routines are called +/// by the C++ runtime \c __cxa_* routines. +/// +/// Note: re-throwing an exception (as opposed to continuing the unwind) +/// is implemented by having the code call \c __cxa_rethrow() which +/// in turn calls \c _Unwind_Resume_or_Rethrow(). +_LIBUNWIND_EXPORT void +_Unwind_Resume(_Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object); + + if (exception_object->private_[0] != 0) { + unw_context_t uc; + + unw_getcontext(&uc); + unwind_phase2_forced(&uc, exception_object, + (_Unwind_Stop_Fn) exception_object->private_[0], + (void *)exception_object->private_[4]); + } else { + // Recover the parameters for the unwind from the exception object + // so we can start unwinding again. + EXCEPTION_RECORD ms_exc; + CONTEXT ms_ctx; + UNWIND_HISTORY_TABLE hist; + + memset(&ms_exc, 0, sizeof(ms_exc)); + memset(&hist, 0, sizeof(hist)); + ms_exc.ExceptionCode = STATUS_GCC_THROW; + ms_exc.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + ms_exc.NumberParameters = 4; + ms_exc.ExceptionInformation[0] = (ULONG_PTR)exception_object; + ms_exc.ExceptionInformation[1] = exception_object->private_[1]; + ms_exc.ExceptionInformation[2] = exception_object->private_[2]; + ms_exc.ExceptionInformation[3] = exception_object->private_[3]; + RtlUnwindEx((PVOID)exception_object->private_[1], + (PVOID)exception_object->private_[2], &ms_exc, + exception_object, &ms_ctx, &hist); + } + + // Clients assume _Unwind_Resume() does not return, so all we can do is abort. + _LIBUNWIND_ABORT("_Unwind_Resume() can't return"); +} + +/// Not used by C++. +/// Unwinds stack, calling "stop" function at each frame. +/// Could be used to implement \c longjmp(). +_LIBUNWIND_EXPORT _Unwind_Reason_Code +_Unwind_ForcedUnwind(_Unwind_Exception *exception_object, + _Unwind_Stop_Fn stop, void *stop_parameter) { + _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)", + (void *)exception_object, (void *)(uintptr_t)stop); + unw_context_t uc; + unw_getcontext(&uc); + + // Mark that this is a forced unwind, so _Unwind_Resume() can do + // the right thing. + exception_object->private_[0] = (uintptr_t) stop; + exception_object->private_[4] = (uintptr_t) stop_parameter; + + // do it + return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter); +} + +/// Called by personality handler during phase 2 to get LSDA for current frame. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { + uintptr_t result = (uintptr_t)_unw_seh_get_disp_ctx((unw_cursor_t *)context)->HandlerData; + _LIBUNWIND_TRACE_API( + "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR, + (void *)context, result); + return result; +} + +/// Called by personality handler during phase 2 to find the start of the +/// function. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetRegionStart(struct _Unwind_Context *context) { + DISPATCHER_CONTEXT *disp = _unw_seh_get_disp_ctx((unw_cursor_t *)context); + uintptr_t result = (uintptr_t)disp->FunctionEntry->BeginAddress + disp->ImageBase; + _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR, + (void *)context, result); + return result; +} + +static int +_unw_init_seh(unw_cursor_t *cursor, CONTEXT *context) { +#ifdef _LIBUNWIND_TARGET_X86_64 + new ((void *)cursor) UnwindCursor( + context, LocalAddressSpace::sThisAddressSpace); + auto *co = reinterpret_cast(cursor); + co->setInfoBasedOnIPRegister(); + return UNW_ESUCCESS; +#elif defined(_LIBUNWIND_TARGET_ARM) + new ((void *)cursor) UnwindCursor( + context, LocalAddressSpace::sThisAddressSpace); + auto *co = reinterpret_cast(cursor); + co->setInfoBasedOnIPRegister(); + return UNW_ESUCCESS; +#elif defined(_LIBUNWIND_TARGET_AARCH64) + new ((void *)cursor) UnwindCursor( + context, LocalAddressSpace::sThisAddressSpace); + auto *co = reinterpret_cast(cursor); + co->setInfoBasedOnIPRegister(); + return UNW_ESUCCESS; +#else + return UNW_EINVAL; +#endif +} + +static DISPATCHER_CONTEXT * +_unw_seh_get_disp_ctx(unw_cursor_t *cursor) { +#ifdef _LIBUNWIND_TARGET_X86_64 + return reinterpret_cast *>(cursor)->getDispatcherContext(); +#elif defined(_LIBUNWIND_TARGET_ARM) + return reinterpret_cast *>(cursor)->getDispatcherContext(); +#elif defined(_LIBUNWIND_TARGET_AARCH64) + return reinterpret_cast *>(cursor)->getDispatcherContext(); +#else + return nullptr; +#endif +} + +static void +_unw_seh_set_disp_ctx(unw_cursor_t *cursor, DISPATCHER_CONTEXT *disp) { +#ifdef _LIBUNWIND_TARGET_X86_64 + reinterpret_cast *>(cursor)->setDispatcherContext(disp); +#elif defined(_LIBUNWIND_TARGET_ARM) + reinterpret_cast *>(cursor)->setDispatcherContext(disp); +#elif defined(_LIBUNWIND_TARGET_AARCH64) + reinterpret_cast *>(cursor)->setDispatcherContext(disp); +#endif +} + +#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) Property changes on: head/contrib/libunwind/src/Unwind-seh.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/Unwind-sjlj.c =================================================================== --- head/contrib/libunwind/src/Unwind-sjlj.c (nonexistent) +++ head/contrib/libunwind/src/Unwind-sjlj.c (revision 345068) @@ -0,0 +1,504 @@ +//===--------------------------- Unwind-sjlj.c ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Implements setjump-longjump based C++ exceptions +// +//===----------------------------------------------------------------------===// + +#include + +#include +#include +#include + +#include "config.h" + +/// With SJLJ based exceptions, any function that has a catch clause or needs to +/// do any clean up when an exception propagates through it, needs to call +/// \c _Unwind_SjLj_Register at the start of the function and +/// \c _Unwind_SjLj_Unregister at the end. The register function is called with +/// the address of a block of memory in the function's stack frame. The runtime +/// keeps a linked list (stack) of these blocks - one per thread. The calling +/// function also sets the personality and lsda fields of the block. + +#if defined(_LIBUNWIND_BUILD_SJLJ_APIS) + +struct _Unwind_FunctionContext { + // next function in stack of handlers + struct _Unwind_FunctionContext *prev; + + // set by calling function before registering to be the landing pad + uint32_t resumeLocation; + + // set by personality handler to be parameters passed to landing pad function + uint32_t resumeParameters[4]; + + // set by calling function before registering + __personality_routine personality; // arm offset=24 + uintptr_t lsda; // arm offset=28 + + // variable length array, contains registers to restore + // 0 = r7, 1 = pc, 2 = sp + void *jbuf[]; +}; + +#if defined(_LIBUNWIND_HAS_NO_THREADS) +# define _LIBUNWIND_THREAD_LOCAL +#else +# if __STDC_VERSION__ >= 201112L +# define _LIBUNWIND_THREAD_LOCAL _Thread_local +# elif defined(_WIN32) +# define _LIBUNWIND_THREAD_LOCAL __declspec(thread) +# elif defined(__GNUC__) || defined(__clang__) +# define _LIBUNWIND_THREAD_LOCAL __thread +# else +# error Unable to create thread local storage +# endif +#endif + + +#if !defined(FOR_DYLD) + +#if defined(__APPLE__) +#include +#else +static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL; +#endif + +static struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() { +#if defined(__APPLE__) + return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key); +#else + return stack; +#endif +} + +static void +__Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc) { +#if defined(__APPLE__) + _pthread_setspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key, fc); +#else + stack = fc; +#endif +} + +#endif + + +/// Called at start of each function that catches exceptions +_LIBUNWIND_EXPORT void +_Unwind_SjLj_Register(struct _Unwind_FunctionContext *fc) { + fc->prev = __Unwind_SjLj_GetTopOfFunctionStack(); + __Unwind_SjLj_SetTopOfFunctionStack(fc); +} + + +/// Called at end of each function that catches exceptions +_LIBUNWIND_EXPORT void +_Unwind_SjLj_Unregister(struct _Unwind_FunctionContext *fc) { + __Unwind_SjLj_SetTopOfFunctionStack(fc->prev); +} + + +static _Unwind_Reason_Code +unwind_phase1(struct _Unwind_Exception *exception_object) { + _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); + _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p", c); + + // walk each frame looking for a place to stop + for (bool handlerNotFound = true; handlerNotFound; c = c->prev) { + + // check for no more frames + if (c == NULL) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): reached " + "bottom => _URC_END_OF_STACK", + exception_object); + return _URC_END_OF_STACK; + } + + _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", c); + // if there is a personality routine, ask it if it will want to stop at this + // frame + if (c->personality != NULL) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): calling " + "personality function %p", + exception_object, c->personality); + _Unwind_Reason_Code personalityResult = (*c->personality)( + 1, _UA_SEARCH_PHASE, exception_object->exception_class, + exception_object, (struct _Unwind_Context *)c); + switch (personalityResult) { + case _URC_HANDLER_FOUND: + // found a catch clause or locals that need destructing in this frame + // stop search and remember function context + handlerNotFound = false; + exception_object->private_2 = (uintptr_t) c; + _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): " + "_URC_HANDLER_FOUND", exception_object); + return _URC_NO_REASON; + + case _URC_CONTINUE_UNWIND: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): " + "_URC_CONTINUE_UNWIND", exception_object); + // continue unwinding + break; + + default: + // something went wrong + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR", + exception_object); + return _URC_FATAL_PHASE1_ERROR; + } + } + } + return _URC_NO_REASON; +} + + +static _Unwind_Reason_Code +unwind_phase2(struct _Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", exception_object); + + // walk each frame until we reach where search phase said to stop + _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); + while (true) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2s(ex_ojb=%p): context=%p", + exception_object, c); + + // check for no more frames + if (c == NULL) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached " + "bottom => _URC_END_OF_STACK", + exception_object); + return _URC_END_OF_STACK; + } + + // if there is a personality routine, tell it we are unwinding + if (c->personality != NULL) { + _Unwind_Action action = _UA_CLEANUP_PHASE; + if ((uintptr_t) c == exception_object->private_2) + action = (_Unwind_Action)( + _UA_CLEANUP_PHASE | + _UA_HANDLER_FRAME); // tell personality this was the frame it marked + // in phase 1 + _Unwind_Reason_Code personalityResult = + (*c->personality)(1, action, exception_object->exception_class, + exception_object, (struct _Unwind_Context *)c); + switch (personalityResult) { + case _URC_CONTINUE_UNWIND: + // continue unwinding + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND", + exception_object); + if ((uintptr_t) c == exception_object->private_2) { + // phase 1 said we would stop at this frame, but we did not... + _LIBUNWIND_ABORT("during phase1 personality function said it would " + "stop here, but now if phase2 it did not stop here"); + } + break; + case _URC_INSTALL_CONTEXT: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): " + "_URC_INSTALL_CONTEXT, will resume at " + "landing pad %p", + exception_object, c->jbuf[1]); + // personality routine says to transfer control to landing pad + // we may get control back if landing pad calls _Unwind_Resume() + __Unwind_SjLj_SetTopOfFunctionStack(c); + __builtin_longjmp(c->jbuf, 1); + // unw_resume() only returns if there was an error + return _URC_FATAL_PHASE2_ERROR; + default: + // something went wrong + _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", + personalityResult); + return _URC_FATAL_PHASE2_ERROR; + } + } + c = c->prev; + } + + // clean up phase did not resume at the frame that the search phase said it + // would + return _URC_FATAL_PHASE2_ERROR; +} + + +static _Unwind_Reason_Code +unwind_phase2_forced(struct _Unwind_Exception *exception_object, + _Unwind_Stop_Fn stop, void *stop_parameter) { + // walk each frame until we reach where search phase said to stop + _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); + while (true) { + + // get next frame (skip over first which is _Unwind_RaiseException) + if (c == NULL) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached " + "bottom => _URC_END_OF_STACK", + exception_object); + return _URC_END_OF_STACK; + } + + // call stop function at each frame + _Unwind_Action action = + (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); + _Unwind_Reason_Code stopResult = + (*stop)(1, action, exception_object->exception_class, exception_object, + (struct _Unwind_Context *)c, stop_parameter); + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "stop function returned %d", + exception_object, stopResult); + if (stopResult != _URC_NO_REASON) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "stopped by stop function", + exception_object); + return _URC_FATAL_PHASE2_ERROR; + } + + // if there is a personality routine, tell it we are unwinding + if (c->personality != NULL) { + __personality_routine p = (__personality_routine) c->personality; + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "calling personality function %p", + exception_object, p); + _Unwind_Reason_Code personalityResult = + (*p)(1, action, exception_object->exception_class, exception_object, + (struct _Unwind_Context *)c); + switch (personalityResult) { + case _URC_CONTINUE_UNWIND: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned _URC_CONTINUE_UNWIND", + exception_object); + // destructors called, continue unwinding + break; + case _URC_INSTALL_CONTEXT: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned _URC_INSTALL_CONTEXT", + exception_object); + // we may get control back if landing pad calls _Unwind_Resume() + __Unwind_SjLj_SetTopOfFunctionStack(c); + __builtin_longjmp(c->jbuf, 1); + break; + default: + // something went wrong + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned %d, " + "_URC_FATAL_PHASE2_ERROR", + exception_object, personalityResult); + return _URC_FATAL_PHASE2_ERROR; + } + } + c = c->prev; + } + + // call stop function one last time and tell it we've reached the end of the + // stack + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " + "function with _UA_END_OF_STACK", + exception_object); + _Unwind_Action lastAction = + (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); + (*stop)(1, lastAction, exception_object->exception_class, exception_object, + (struct _Unwind_Context *)c, stop_parameter); + + // clean up phase did not resume at the frame that the search phase said it + // would + return _URC_FATAL_PHASE2_ERROR; +} + + +/// Called by __cxa_throw. Only returns if there is a fatal error +_LIBUNWIND_EXPORT _Unwind_Reason_Code +_Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)", exception_object); + + // mark that this is a non-forced unwind, so _Unwind_Resume() can do the right + // thing + exception_object->private_1 = 0; + exception_object->private_2 = 0; + + // phase 1: the search phase + _Unwind_Reason_Code phase1 = unwind_phase1(exception_object); + if (phase1 != _URC_NO_REASON) + return phase1; + + // phase 2: the clean up phase + return unwind_phase2(exception_object); +} + + + +/// When _Unwind_RaiseException() is in phase2, it hands control +/// to the personality function at each frame. The personality +/// may force a jump to a landing pad in that function, the landing +/// pad code may then call _Unwind_Resume() to continue with the +/// unwinding. Note: the call to _Unwind_Resume() is from compiler +/// geneated user code. All other _Unwind_* routines are called +/// by the C++ runtime __cxa_* routines. +/// +/// Re-throwing an exception is implemented by having the code call +/// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow() +_LIBUNWIND_EXPORT void +_Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)", exception_object); + + if (exception_object->private_1 != 0) + unwind_phase2_forced(exception_object, + (_Unwind_Stop_Fn) exception_object->private_1, + (void *)exception_object->private_2); + else + unwind_phase2(exception_object); + + // clients assume _Unwind_Resume() does not return, so all we can do is abort. + _LIBUNWIND_ABORT("_Unwind_SjLj_Resume() can't return"); +} + + +/// Called by __cxa_rethrow(). +_LIBUNWIND_EXPORT _Unwind_Reason_Code +_Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), " + "private_1=%ld", + exception_object, exception_object->private_1); + // If this is non-forced and a stopping place was found, then this is a + // re-throw. + // Call _Unwind_RaiseException() as if this was a new exception. + if (exception_object->private_1 == 0) { + return _Unwind_SjLj_RaiseException(exception_object); + // should return if there is no catch clause, so that __cxa_rethrow can call + // std::terminate() + } + + // Call through to _Unwind_Resume() which distiguishes between forced and + // regular exceptions. + _Unwind_SjLj_Resume(exception_object); + _LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called " + "_Unwind_SjLj_Resume() which unexpectedly returned"); +} + + +/// Called by personality handler during phase 2 to get LSDA for current frame. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { + _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; + _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) " + "=> 0x%0lX", context, ufc->lsda); + return ufc->lsda; +} + + +/// Called by personality handler during phase 2 to get register values. +_LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, + int index) { + _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)", + context, index); + _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; + return ufc->resumeParameters[index]; +} + + +/// Called by personality handler during phase 2 to alter register values. +_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, + uintptr_t new_value) { + _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)" + , context, index, new_value); + _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; + ufc->resumeParameters[index] = new_value; +} + + +/// Called by personality handler during phase 2 to get instruction pointer. +_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { + _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; + _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%lX", context, + ufc->resumeLocation + 1); + return ufc->resumeLocation + 1; +} + + +/// Called by personality handler during phase 2 to get instruction pointer. +/// ipBefore is a boolean that says if IP is already adjusted to be the call +/// site address. Normally IP is the return address. +_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, + int *ipBefore) { + _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; + *ipBefore = 0; + _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX", + context, ipBefore, ufc->resumeLocation + 1); + return ufc->resumeLocation + 1; +} + + +/// Called by personality handler during phase 2 to alter instruction pointer. +_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, + uintptr_t new_value) { + _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0lX)", + context, new_value); + _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; + ufc->resumeLocation = new_value - 1; +} + + +/// Called by personality handler during phase 2 to find the start of the +/// function. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetRegionStart(struct _Unwind_Context *context) { + // Not supported or needed for sjlj based unwinding + (void)context; + _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)", context); + return 0; +} + + +/// Called by personality handler during phase 2 if a foreign exception +/// is caught. +_LIBUNWIND_EXPORT void +_Unwind_DeleteException(struct _Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)", + exception_object); + if (exception_object->exception_cleanup != NULL) + (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, + exception_object); +} + + + +/// Called by personality handler during phase 2 to get base address for data +/// relative encodings. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetDataRelBase(struct _Unwind_Context *context) { + // Not supported or needed for sjlj based unwinding + (void)context; + _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", context); + _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented"); +} + + +/// Called by personality handler during phase 2 to get base address for text +/// relative encodings. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetTextRelBase(struct _Unwind_Context *context) { + // Not supported or needed for sjlj based unwinding + (void)context; + _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", context); + _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented"); +} + + +/// Called by personality handler to get "Call Frame Area" for current frame. +_LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { + _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)", context); + if (context != NULL) { + _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; + // Setjmp/longjmp based exceptions don't have a true CFA. + // Instead, the SP in the jmpbuf is the closest approximation. + return (uintptr_t) ufc->jbuf[2]; + } + return 0; +} + +#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS) Property changes on: head/contrib/libunwind/src/Unwind-sjlj.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/UnwindCursor.hpp =================================================================== --- head/contrib/libunwind/src/UnwindCursor.hpp (nonexistent) +++ head/contrib/libunwind/src/UnwindCursor.hpp (revision 345068) @@ -0,0 +1,1981 @@ +//===------------------------- UnwindCursor.hpp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// C++ interface to lower levels of libunwind +//===----------------------------------------------------------------------===// + +#ifndef __UNWINDCURSOR_HPP__ +#define __UNWINDCURSOR_HPP__ + +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #include + #include +#endif +#ifdef __APPLE__ + #include +#endif + +#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) +// Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and +// earlier) SDKs. +// MinGW-w64 has always provided this struct. + #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \ + !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000 +struct _DISPATCHER_CONTEXT { + ULONG64 ControlPc; + ULONG64 ImageBase; + PRUNTIME_FUNCTION FunctionEntry; + ULONG64 EstablisherFrame; + ULONG64 TargetIp; + PCONTEXT ContextRecord; + PEXCEPTION_ROUTINE LanguageHandler; + PVOID HandlerData; + PUNWIND_HISTORY_TABLE HistoryTable; + ULONG ScopeIndex; + ULONG Fill0; +}; + #endif + +struct UNWIND_INFO { + uint8_t Version : 3; + uint8_t Flags : 5; + uint8_t SizeOfProlog; + uint8_t CountOfCodes; + uint8_t FrameRegister : 4; + uint8_t FrameOffset : 4; + uint16_t UnwindCodes[2]; +}; + +extern "C" _Unwind_Reason_Code __libunwind_seh_personality( + int, _Unwind_Action, uint64_t, _Unwind_Exception *, + struct _Unwind_Context *); + +#endif + +#include "config.h" + +#include "AddressSpace.hpp" +#include "CompactUnwinder.hpp" +#include "config.h" +#include "DwarfInstructions.hpp" +#include "EHHeaderParser.hpp" +#include "libunwind.h" +#include "Registers.hpp" +#include "RWMutex.hpp" +#include "Unwind-EHABI.h" + +namespace libunwind { + +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) +/// Cache of recently found FDEs. +template +class _LIBUNWIND_HIDDEN DwarfFDECache { + typedef typename A::pint_t pint_t; +public: + static pint_t findFDE(pint_t mh, pint_t pc); + static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde); + static void removeAllIn(pint_t mh); + static void iterateCacheEntries(void (*func)(unw_word_t ip_start, + unw_word_t ip_end, + unw_word_t fde, unw_word_t mh)); + +private: + + struct entry { + pint_t mh; + pint_t ip_start; + pint_t ip_end; + pint_t fde; + }; + + // These fields are all static to avoid needing an initializer. + // There is only one instance of this class per process. + static RWMutex _lock; +#ifdef __APPLE__ + static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide); + static bool _registeredForDyldUnloads; +#endif + // Can't use std::vector<> here because this code is below libc++. + static entry *_buffer; + static entry *_bufferUsed; + static entry *_bufferEnd; + static entry _initialBuffer[64]; +}; + +template +typename DwarfFDECache::entry * +DwarfFDECache::_buffer = _initialBuffer; + +template +typename DwarfFDECache::entry * +DwarfFDECache::_bufferUsed = _initialBuffer; + +template +typename DwarfFDECache::entry * +DwarfFDECache::_bufferEnd = &_initialBuffer[64]; + +template +typename DwarfFDECache::entry DwarfFDECache::_initialBuffer[64]; + +template +RWMutex DwarfFDECache::_lock; + +#ifdef __APPLE__ +template +bool DwarfFDECache::_registeredForDyldUnloads = false; +#endif + +template +typename A::pint_t DwarfFDECache::findFDE(pint_t mh, pint_t pc) { + pint_t result = 0; + _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); + for (entry *p = _buffer; p < _bufferUsed; ++p) { + if ((mh == p->mh) || (mh == 0)) { + if ((p->ip_start <= pc) && (pc < p->ip_end)) { + result = p->fde; + break; + } + } + } + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared()); + return result; +} + +template +void DwarfFDECache::add(pint_t mh, pint_t ip_start, pint_t ip_end, + pint_t fde) { +#if !defined(_LIBUNWIND_NO_HEAP) + _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); + if (_bufferUsed >= _bufferEnd) { + size_t oldSize = (size_t)(_bufferEnd - _buffer); + size_t newSize = oldSize * 4; + // Can't use operator new (we are below it). + entry *newBuffer = (entry *)malloc(newSize * sizeof(entry)); + memcpy(newBuffer, _buffer, oldSize * sizeof(entry)); + if (_buffer != _initialBuffer) + free(_buffer); + _buffer = newBuffer; + _bufferUsed = &newBuffer[oldSize]; + _bufferEnd = &newBuffer[newSize]; + } + _bufferUsed->mh = mh; + _bufferUsed->ip_start = ip_start; + _bufferUsed->ip_end = ip_end; + _bufferUsed->fde = fde; + ++_bufferUsed; +#ifdef __APPLE__ + if (!_registeredForDyldUnloads) { + _dyld_register_func_for_remove_image(&dyldUnloadHook); + _registeredForDyldUnloads = true; + } +#endif + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); +#endif +} + +template +void DwarfFDECache::removeAllIn(pint_t mh) { + _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); + entry *d = _buffer; + for (const entry *s = _buffer; s < _bufferUsed; ++s) { + if (s->mh != mh) { + if (d != s) + *d = *s; + ++d; + } + } + _bufferUsed = d; + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); +} + +#ifdef __APPLE__ +template +void DwarfFDECache::dyldUnloadHook(const struct mach_header *mh, intptr_t ) { + removeAllIn((pint_t) mh); +} +#endif + +template +void DwarfFDECache::iterateCacheEntries(void (*func)( + unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { + _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); + for (entry *p = _buffer; p < _bufferUsed; ++p) { + (*func)(p->ip_start, p->ip_end, p->fde, p->mh); + } + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); +} +#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + + +#define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field)) + +#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) +template class UnwindSectionHeader { +public: + UnwindSectionHeader(A &addressSpace, typename A::pint_t addr) + : _addressSpace(addressSpace), _addr(addr) {} + + uint32_t version() const { + return _addressSpace.get32(_addr + + offsetof(unwind_info_section_header, version)); + } + uint32_t commonEncodingsArraySectionOffset() const { + return _addressSpace.get32(_addr + + offsetof(unwind_info_section_header, + commonEncodingsArraySectionOffset)); + } + uint32_t commonEncodingsArrayCount() const { + return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, + commonEncodingsArrayCount)); + } + uint32_t personalityArraySectionOffset() const { + return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, + personalityArraySectionOffset)); + } + uint32_t personalityArrayCount() const { + return _addressSpace.get32( + _addr + offsetof(unwind_info_section_header, personalityArrayCount)); + } + uint32_t indexSectionOffset() const { + return _addressSpace.get32( + _addr + offsetof(unwind_info_section_header, indexSectionOffset)); + } + uint32_t indexCount() const { + return _addressSpace.get32( + _addr + offsetof(unwind_info_section_header, indexCount)); + } + +private: + A &_addressSpace; + typename A::pint_t _addr; +}; + +template class UnwindSectionIndexArray { +public: + UnwindSectionIndexArray(A &addressSpace, typename A::pint_t addr) + : _addressSpace(addressSpace), _addr(addr) {} + + uint32_t functionOffset(uint32_t index) const { + return _addressSpace.get32( + _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, + functionOffset)); + } + uint32_t secondLevelPagesSectionOffset(uint32_t index) const { + return _addressSpace.get32( + _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, + secondLevelPagesSectionOffset)); + } + uint32_t lsdaIndexArraySectionOffset(uint32_t index) const { + return _addressSpace.get32( + _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, + lsdaIndexArraySectionOffset)); + } + +private: + A &_addressSpace; + typename A::pint_t _addr; +}; + +template class UnwindSectionRegularPageHeader { +public: + UnwindSectionRegularPageHeader(A &addressSpace, typename A::pint_t addr) + : _addressSpace(addressSpace), _addr(addr) {} + + uint32_t kind() const { + return _addressSpace.get32( + _addr + offsetof(unwind_info_regular_second_level_page_header, kind)); + } + uint16_t entryPageOffset() const { + return _addressSpace.get16( + _addr + offsetof(unwind_info_regular_second_level_page_header, + entryPageOffset)); + } + uint16_t entryCount() const { + return _addressSpace.get16( + _addr + + offsetof(unwind_info_regular_second_level_page_header, entryCount)); + } + +private: + A &_addressSpace; + typename A::pint_t _addr; +}; + +template class UnwindSectionRegularArray { +public: + UnwindSectionRegularArray(A &addressSpace, typename A::pint_t addr) + : _addressSpace(addressSpace), _addr(addr) {} + + uint32_t functionOffset(uint32_t index) const { + return _addressSpace.get32( + _addr + arrayoffsetof(unwind_info_regular_second_level_entry, index, + functionOffset)); + } + uint32_t encoding(uint32_t index) const { + return _addressSpace.get32( + _addr + + arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding)); + } + +private: + A &_addressSpace; + typename A::pint_t _addr; +}; + +template class UnwindSectionCompressedPageHeader { +public: + UnwindSectionCompressedPageHeader(A &addressSpace, typename A::pint_t addr) + : _addressSpace(addressSpace), _addr(addr) {} + + uint32_t kind() const { + return _addressSpace.get32( + _addr + + offsetof(unwind_info_compressed_second_level_page_header, kind)); + } + uint16_t entryPageOffset() const { + return _addressSpace.get16( + _addr + offsetof(unwind_info_compressed_second_level_page_header, + entryPageOffset)); + } + uint16_t entryCount() const { + return _addressSpace.get16( + _addr + + offsetof(unwind_info_compressed_second_level_page_header, entryCount)); + } + uint16_t encodingsPageOffset() const { + return _addressSpace.get16( + _addr + offsetof(unwind_info_compressed_second_level_page_header, + encodingsPageOffset)); + } + uint16_t encodingsCount() const { + return _addressSpace.get16( + _addr + offsetof(unwind_info_compressed_second_level_page_header, + encodingsCount)); + } + +private: + A &_addressSpace; + typename A::pint_t _addr; +}; + +template class UnwindSectionCompressedArray { +public: + UnwindSectionCompressedArray(A &addressSpace, typename A::pint_t addr) + : _addressSpace(addressSpace), _addr(addr) {} + + uint32_t functionOffset(uint32_t index) const { + return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET( + _addressSpace.get32(_addr + index * sizeof(uint32_t))); + } + uint16_t encodingIndex(uint32_t index) const { + return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX( + _addressSpace.get32(_addr + index * sizeof(uint32_t))); + } + +private: + A &_addressSpace; + typename A::pint_t _addr; +}; + +template class UnwindSectionLsdaArray { +public: + UnwindSectionLsdaArray(A &addressSpace, typename A::pint_t addr) + : _addressSpace(addressSpace), _addr(addr) {} + + uint32_t functionOffset(uint32_t index) const { + return _addressSpace.get32( + _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, + index, functionOffset)); + } + uint32_t lsdaOffset(uint32_t index) const { + return _addressSpace.get32( + _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, + index, lsdaOffset)); + } + +private: + A &_addressSpace; + typename A::pint_t _addr; +}; +#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) + +class _LIBUNWIND_HIDDEN AbstractUnwindCursor { +public: + // NOTE: provide a class specific placement deallocation function (S5.3.4 p20) + // This avoids an unnecessary dependency to libc++abi. + void operator delete(void *, size_t) {} + + virtual ~AbstractUnwindCursor() {} + virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); } + virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); } + virtual void setReg(int, unw_word_t) { + _LIBUNWIND_ABORT("setReg not implemented"); + } + virtual bool validFloatReg(int) { + _LIBUNWIND_ABORT("validFloatReg not implemented"); + } + virtual unw_fpreg_t getFloatReg(int) { + _LIBUNWIND_ABORT("getFloatReg not implemented"); + } + virtual void setFloatReg(int, unw_fpreg_t) { + _LIBUNWIND_ABORT("setFloatReg not implemented"); + } + virtual int step() { _LIBUNWIND_ABORT("step not implemented"); } + virtual void getInfo(unw_proc_info_t *) { + _LIBUNWIND_ABORT("getInfo not implemented"); + } + virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); } + virtual bool isSignalFrame() { + _LIBUNWIND_ABORT("isSignalFrame not implemented"); + } + virtual bool getFunctionName(char *, size_t, unw_word_t *) { + _LIBUNWIND_ABORT("getFunctionName not implemented"); + } + virtual void setInfoBasedOnIPRegister(bool = false) { + _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented"); + } + virtual const char *getRegisterName(int) { + _LIBUNWIND_ABORT("getRegisterName not implemented"); + } +#ifdef __arm__ + virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); } +#endif +}; + +#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) + +/// \c UnwindCursor contains all state (including all register values) during +/// an unwind. This is normally stack-allocated inside a unw_cursor_t. +template +class UnwindCursor : public AbstractUnwindCursor { + typedef typename A::pint_t pint_t; +public: + UnwindCursor(unw_context_t *context, A &as); + UnwindCursor(CONTEXT *context, A &as); + UnwindCursor(A &as, void *threadArg); + virtual ~UnwindCursor() {} + virtual bool validReg(int); + virtual unw_word_t getReg(int); + virtual void setReg(int, unw_word_t); + virtual bool validFloatReg(int); + virtual unw_fpreg_t getFloatReg(int); + virtual void setFloatReg(int, unw_fpreg_t); + virtual int step(); + virtual void getInfo(unw_proc_info_t *); + virtual void jumpto(); + virtual bool isSignalFrame(); + virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); + virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); + virtual const char *getRegisterName(int num); +#ifdef __arm__ + virtual void saveVFPAsX(); +#endif + + DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; } + void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; } + +private: + + pint_t getLastPC() const { return _dispContext.ControlPc; } + void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; } + RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) { + _dispContext.FunctionEntry = RtlLookupFunctionEntry(pc, + &_dispContext.ImageBase, + _dispContext.HistoryTable); + *base = _dispContext.ImageBase; + return _dispContext.FunctionEntry; + } + bool getInfoFromSEH(pint_t pc); + int stepWithSEHData() { + _dispContext.LanguageHandler = RtlVirtualUnwind(UNW_FLAG_UHANDLER, + _dispContext.ImageBase, + _dispContext.ControlPc, + _dispContext.FunctionEntry, + _dispContext.ContextRecord, + &_dispContext.HandlerData, + &_dispContext.EstablisherFrame, + NULL); + // Update some fields of the unwind info now, since we have them. + _info.lsda = reinterpret_cast(_dispContext.HandlerData); + if (_dispContext.LanguageHandler) { + _info.handler = reinterpret_cast(__libunwind_seh_personality); + } else + _info.handler = 0; + return UNW_STEP_SUCCESS; + } + + A &_addressSpace; + unw_proc_info_t _info; + DISPATCHER_CONTEXT _dispContext; + CONTEXT _msContext; + UNWIND_HISTORY_TABLE _histTable; + bool _unwindInfoMissing; +}; + + +template +UnwindCursor::UnwindCursor(unw_context_t *context, A &as) + : _addressSpace(as), _unwindInfoMissing(false) { + static_assert((check_fit, unw_cursor_t>::does_fit), + "UnwindCursor<> does not fit in unw_cursor_t"); + memset(&_info, 0, sizeof(_info)); + memset(&_histTable, 0, sizeof(_histTable)); + _dispContext.ContextRecord = &_msContext; + _dispContext.HistoryTable = &_histTable; + // Initialize MS context from ours. + R r(context); + _msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT; +#if defined(_LIBUNWIND_TARGET_X86_64) + _msContext.Rax = r.getRegister(UNW_X86_64_RAX); + _msContext.Rcx = r.getRegister(UNW_X86_64_RCX); + _msContext.Rdx = r.getRegister(UNW_X86_64_RDX); + _msContext.Rbx = r.getRegister(UNW_X86_64_RBX); + _msContext.Rsp = r.getRegister(UNW_X86_64_RSP); + _msContext.Rbp = r.getRegister(UNW_X86_64_RBP); + _msContext.Rsi = r.getRegister(UNW_X86_64_RSI); + _msContext.Rdi = r.getRegister(UNW_X86_64_RDI); + _msContext.R8 = r.getRegister(UNW_X86_64_R8); + _msContext.R9 = r.getRegister(UNW_X86_64_R9); + _msContext.R10 = r.getRegister(UNW_X86_64_R10); + _msContext.R11 = r.getRegister(UNW_X86_64_R11); + _msContext.R12 = r.getRegister(UNW_X86_64_R12); + _msContext.R13 = r.getRegister(UNW_X86_64_R13); + _msContext.R14 = r.getRegister(UNW_X86_64_R14); + _msContext.R15 = r.getRegister(UNW_X86_64_R15); + _msContext.Rip = r.getRegister(UNW_REG_IP); + union { + v128 v; + M128A m; + } t; + t.v = r.getVectorRegister(UNW_X86_64_XMM0); + _msContext.Xmm0 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM1); + _msContext.Xmm1 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM2); + _msContext.Xmm2 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM3); + _msContext.Xmm3 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM4); + _msContext.Xmm4 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM5); + _msContext.Xmm5 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM6); + _msContext.Xmm6 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM7); + _msContext.Xmm7 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM8); + _msContext.Xmm8 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM9); + _msContext.Xmm9 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM10); + _msContext.Xmm10 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM11); + _msContext.Xmm11 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM12); + _msContext.Xmm12 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM13); + _msContext.Xmm13 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM14); + _msContext.Xmm14 = t.m; + t.v = r.getVectorRegister(UNW_X86_64_XMM15); + _msContext.Xmm15 = t.m; +#elif defined(_LIBUNWIND_TARGET_ARM) + _msContext.R0 = r.getRegister(UNW_ARM_R0); + _msContext.R1 = r.getRegister(UNW_ARM_R1); + _msContext.R2 = r.getRegister(UNW_ARM_R2); + _msContext.R3 = r.getRegister(UNW_ARM_R3); + _msContext.R4 = r.getRegister(UNW_ARM_R4); + _msContext.R5 = r.getRegister(UNW_ARM_R5); + _msContext.R6 = r.getRegister(UNW_ARM_R6); + _msContext.R7 = r.getRegister(UNW_ARM_R7); + _msContext.R8 = r.getRegister(UNW_ARM_R8); + _msContext.R9 = r.getRegister(UNW_ARM_R9); + _msContext.R10 = r.getRegister(UNW_ARM_R10); + _msContext.R11 = r.getRegister(UNW_ARM_R11); + _msContext.R12 = r.getRegister(UNW_ARM_R12); + _msContext.Sp = r.getRegister(UNW_ARM_SP); + _msContext.Lr = r.getRegister(UNW_ARM_LR); + _msContext.Pc = r.getRegister(UNW_ARM_IP); + for (int i = UNW_ARM_D0; i <= UNW_ARM_D31; ++i) { + union { + uint64_t w; + double d; + } d; + d.d = r.getFloatRegister(i); + _msContext.D[i - UNW_ARM_D0] = d.w; + } +#elif defined(_LIBUNWIND_TARGET_AARCH64) + for (int i = UNW_ARM64_X0; i <= UNW_ARM64_X30; ++i) + _msContext.X[i - UNW_ARM64_X0] = r.getRegister(i); + _msContext.Sp = r.getRegister(UNW_REG_SP); + _msContext.Pc = r.getRegister(UNW_REG_IP); + for (int i = UNW_ARM64_D0; i <= UNW_ARM64_D31; ++i) + _msContext.V[i - UNW_ARM64_D0].D[0] = r.getFloatRegister(i); +#endif +} + +template +UnwindCursor::UnwindCursor(CONTEXT *context, A &as) + : _addressSpace(as), _unwindInfoMissing(false) { + static_assert((check_fit, unw_cursor_t>::does_fit), + "UnwindCursor<> does not fit in unw_cursor_t"); + memset(&_info, 0, sizeof(_info)); + memset(&_histTable, 0, sizeof(_histTable)); + _dispContext.ContextRecord = &_msContext; + _dispContext.HistoryTable = &_histTable; + _msContext = *context; +} + + +template +bool UnwindCursor::validReg(int regNum) { + if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true; +#if defined(_LIBUNWIND_TARGET_X86_64) + if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true; +#elif defined(_LIBUNWIND_TARGET_ARM) + if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) return true; +#elif defined(_LIBUNWIND_TARGET_AARCH64) + if (regNum >= UNW_ARM64_X0 && regNum <= UNW_ARM64_X30) return true; +#endif + return false; +} + +template +unw_word_t UnwindCursor::getReg(int regNum) { + switch (regNum) { +#if defined(_LIBUNWIND_TARGET_X86_64) + case UNW_REG_IP: return _msContext.Rip; + case UNW_X86_64_RAX: return _msContext.Rax; + case UNW_X86_64_RDX: return _msContext.Rdx; + case UNW_X86_64_RCX: return _msContext.Rcx; + case UNW_X86_64_RBX: return _msContext.Rbx; + case UNW_REG_SP: + case UNW_X86_64_RSP: return _msContext.Rsp; + case UNW_X86_64_RBP: return _msContext.Rbp; + case UNW_X86_64_RSI: return _msContext.Rsi; + case UNW_X86_64_RDI: return _msContext.Rdi; + case UNW_X86_64_R8: return _msContext.R8; + case UNW_X86_64_R9: return _msContext.R9; + case UNW_X86_64_R10: return _msContext.R10; + case UNW_X86_64_R11: return _msContext.R11; + case UNW_X86_64_R12: return _msContext.R12; + case UNW_X86_64_R13: return _msContext.R13; + case UNW_X86_64_R14: return _msContext.R14; + case UNW_X86_64_R15: return _msContext.R15; +#elif defined(_LIBUNWIND_TARGET_ARM) + case UNW_ARM_R0: return _msContext.R0; + case UNW_ARM_R1: return _msContext.R1; + case UNW_ARM_R2: return _msContext.R2; + case UNW_ARM_R3: return _msContext.R3; + case UNW_ARM_R4: return _msContext.R4; + case UNW_ARM_R5: return _msContext.R5; + case UNW_ARM_R6: return _msContext.R6; + case UNW_ARM_R7: return _msContext.R7; + case UNW_ARM_R8: return _msContext.R8; + case UNW_ARM_R9: return _msContext.R9; + case UNW_ARM_R10: return _msContext.R10; + case UNW_ARM_R11: return _msContext.R11; + case UNW_ARM_R12: return _msContext.R12; + case UNW_REG_SP: + case UNW_ARM_SP: return _msContext.Sp; + case UNW_ARM_LR: return _msContext.Lr; + case UNW_REG_IP: + case UNW_ARM_IP: return _msContext.Pc; +#elif defined(_LIBUNWIND_TARGET_AARCH64) + case UNW_REG_SP: return _msContext.Sp; + case UNW_REG_IP: return _msContext.Pc; + default: return _msContext.X[regNum - UNW_ARM64_X0]; +#endif + } + _LIBUNWIND_ABORT("unsupported register"); +} + +template +void UnwindCursor::setReg(int regNum, unw_word_t value) { + switch (regNum) { +#if defined(_LIBUNWIND_TARGET_X86_64) + case UNW_REG_IP: _msContext.Rip = value; break; + case UNW_X86_64_RAX: _msContext.Rax = value; break; + case UNW_X86_64_RDX: _msContext.Rdx = value; break; + case UNW_X86_64_RCX: _msContext.Rcx = value; break; + case UNW_X86_64_RBX: _msContext.Rbx = value; break; + case UNW_REG_SP: + case UNW_X86_64_RSP: _msContext.Rsp = value; break; + case UNW_X86_64_RBP: _msContext.Rbp = value; break; + case UNW_X86_64_RSI: _msContext.Rsi = value; break; + case UNW_X86_64_RDI: _msContext.Rdi = value; break; + case UNW_X86_64_R8: _msContext.R8 = value; break; + case UNW_X86_64_R9: _msContext.R9 = value; break; + case UNW_X86_64_R10: _msContext.R10 = value; break; + case UNW_X86_64_R11: _msContext.R11 = value; break; + case UNW_X86_64_R12: _msContext.R12 = value; break; + case UNW_X86_64_R13: _msContext.R13 = value; break; + case UNW_X86_64_R14: _msContext.R14 = value; break; + case UNW_X86_64_R15: _msContext.R15 = value; break; +#elif defined(_LIBUNWIND_TARGET_ARM) + case UNW_ARM_R0: _msContext.R0 = value; break; + case UNW_ARM_R1: _msContext.R1 = value; break; + case UNW_ARM_R2: _msContext.R2 = value; break; + case UNW_ARM_R3: _msContext.R3 = value; break; + case UNW_ARM_R4: _msContext.R4 = value; break; + case UNW_ARM_R5: _msContext.R5 = value; break; + case UNW_ARM_R6: _msContext.R6 = value; break; + case UNW_ARM_R7: _msContext.R7 = value; break; + case UNW_ARM_R8: _msContext.R8 = value; break; + case UNW_ARM_R9: _msContext.R9 = value; break; + case UNW_ARM_R10: _msContext.R10 = value; break; + case UNW_ARM_R11: _msContext.R11 = value; break; + case UNW_ARM_R12: _msContext.R12 = value; break; + case UNW_REG_SP: + case UNW_ARM_SP: _msContext.Sp = value; break; + case UNW_ARM_LR: _msContext.Lr = value; break; + case UNW_REG_IP: + case UNW_ARM_IP: _msContext.Pc = value; break; +#elif defined(_LIBUNWIND_TARGET_AARCH64) + case UNW_REG_SP: _msContext.Sp = value; break; + case UNW_REG_IP: _msContext.Pc = value; break; + case UNW_ARM64_X0: + case UNW_ARM64_X1: + case UNW_ARM64_X2: + case UNW_ARM64_X3: + case UNW_ARM64_X4: + case UNW_ARM64_X5: + case UNW_ARM64_X6: + case UNW_ARM64_X7: + case UNW_ARM64_X8: + case UNW_ARM64_X9: + case UNW_ARM64_X10: + case UNW_ARM64_X11: + case UNW_ARM64_X12: + case UNW_ARM64_X13: + case UNW_ARM64_X14: + case UNW_ARM64_X15: + case UNW_ARM64_X16: + case UNW_ARM64_X17: + case UNW_ARM64_X18: + case UNW_ARM64_X19: + case UNW_ARM64_X20: + case UNW_ARM64_X21: + case UNW_ARM64_X22: + case UNW_ARM64_X23: + case UNW_ARM64_X24: + case UNW_ARM64_X25: + case UNW_ARM64_X26: + case UNW_ARM64_X27: + case UNW_ARM64_X28: + case UNW_ARM64_FP: + case UNW_ARM64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break; +#endif + default: + _LIBUNWIND_ABORT("unsupported register"); + } +} + +template +bool UnwindCursor::validFloatReg(int regNum) { +#if defined(_LIBUNWIND_TARGET_ARM) + if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true; + if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true; +#elif defined(_LIBUNWIND_TARGET_AARCH64) + if (regNum >= UNW_ARM64_D0 && regNum <= UNW_ARM64_D31) return true; +#endif + return false; +} + +template +unw_fpreg_t UnwindCursor::getFloatReg(int regNum) { +#if defined(_LIBUNWIND_TARGET_ARM) + if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) { + union { + uint32_t w; + float f; + } d; + d.w = _msContext.S[regNum - UNW_ARM_S0]; + return d.f; + } + if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) { + union { + uint64_t w; + double d; + } d; + d.w = _msContext.D[regNum - UNW_ARM_D0]; + return d.d; + } + _LIBUNWIND_ABORT("unsupported float register"); +#elif defined(_LIBUNWIND_TARGET_AARCH64) + return _msContext.V[regNum - UNW_ARM64_D0].D[0]; +#else + _LIBUNWIND_ABORT("float registers unimplemented"); +#endif +} + +template +void UnwindCursor::setFloatReg(int regNum, unw_fpreg_t value) { +#if defined(_LIBUNWIND_TARGET_ARM) + if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) { + union { + uint32_t w; + float f; + } d; + d.f = value; + _msContext.S[regNum - UNW_ARM_S0] = d.w; + } + if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) { + union { + uint64_t w; + double d; + } d; + d.d = value; + _msContext.D[regNum - UNW_ARM_D0] = d.w; + } + _LIBUNWIND_ABORT("unsupported float register"); +#elif defined(_LIBUNWIND_TARGET_AARCH64) + _msContext.V[regNum - UNW_ARM64_D0].D[0] = value; +#else + _LIBUNWIND_ABORT("float registers unimplemented"); +#endif +} + +template void UnwindCursor::jumpto() { + RtlRestoreContext(&_msContext, nullptr); +} + +#ifdef __arm__ +template void UnwindCursor::saveVFPAsX() {} +#endif + +template +const char *UnwindCursor::getRegisterName(int regNum) { + return R::getRegisterName(regNum); +} + +template bool UnwindCursor::isSignalFrame() { + return false; +} + +#else // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32) + +/// UnwindCursor contains all state (including all register values) during +/// an unwind. This is normally stack allocated inside a unw_cursor_t. +template +class UnwindCursor : public AbstractUnwindCursor{ + typedef typename A::pint_t pint_t; +public: + UnwindCursor(unw_context_t *context, A &as); + UnwindCursor(A &as, void *threadArg); + virtual ~UnwindCursor() {} + virtual bool validReg(int); + virtual unw_word_t getReg(int); + virtual void setReg(int, unw_word_t); + virtual bool validFloatReg(int); + virtual unw_fpreg_t getFloatReg(int); + virtual void setFloatReg(int, unw_fpreg_t); + virtual int step(); + virtual void getInfo(unw_proc_info_t *); + virtual void jumpto(); + virtual bool isSignalFrame(); + virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); + virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); + virtual const char *getRegisterName(int num); +#ifdef __arm__ + virtual void saveVFPAsX(); +#endif + +private: + +#if defined(_LIBUNWIND_ARM_EHABI) + bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections §s); + + int stepWithEHABI() { + size_t len = 0; + size_t off = 0; + // FIXME: Calling decode_eht_entry() here is violating the libunwind + // abstraction layer. + const uint32_t *ehtp = + decode_eht_entry(reinterpret_cast(_info.unwind_info), + &off, &len); + if (_Unwind_VRS_Interpret((_Unwind_Context *)this, ehtp, off, len) != + _URC_CONTINUE_UNWIND) + return UNW_STEP_END; + return UNW_STEP_SUCCESS; + } +#endif + +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections §s, + uint32_t fdeSectionOffsetHint=0); + int stepWithDwarfFDE() { + return DwarfInstructions::stepWithDwarf(_addressSpace, + (pint_t)this->getReg(UNW_REG_IP), + (pint_t)_info.unwind_info, + _registers); + } +#endif + +#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) + bool getInfoFromCompactEncodingSection(pint_t pc, + const UnwindInfoSections §s); + int stepWithCompactEncoding() { + #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + if ( compactSaysUseDwarf() ) + return stepWithDwarfFDE(); + #endif + R dummy; + return stepWithCompactEncoding(dummy); + } + +#if defined(_LIBUNWIND_TARGET_X86_64) + int stepWithCompactEncoding(Registers_x86_64 &) { + return CompactUnwinder_x86_64::stepWithCompactEncoding( + _info.format, _info.start_ip, _addressSpace, _registers); + } +#endif + +#if defined(_LIBUNWIND_TARGET_I386) + int stepWithCompactEncoding(Registers_x86 &) { + return CompactUnwinder_x86::stepWithCompactEncoding( + _info.format, (uint32_t)_info.start_ip, _addressSpace, _registers); + } +#endif + +#if defined(_LIBUNWIND_TARGET_PPC) + int stepWithCompactEncoding(Registers_ppc &) { + return UNW_EINVAL; + } +#endif + +#if defined(_LIBUNWIND_TARGET_PPC64) + int stepWithCompactEncoding(Registers_ppc64 &) { + return UNW_EINVAL; + } +#endif + + +#if defined(_LIBUNWIND_TARGET_AARCH64) + int stepWithCompactEncoding(Registers_arm64 &) { + return CompactUnwinder_arm64::stepWithCompactEncoding( + _info.format, _info.start_ip, _addressSpace, _registers); + } +#endif + +#if defined(_LIBUNWIND_TARGET_MIPS_O32) + int stepWithCompactEncoding(Registers_mips_o32 &) { + return UNW_EINVAL; + } +#endif + +#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) + int stepWithCompactEncoding(Registers_mips_newabi &) { + return UNW_EINVAL; + } +#endif + +#if defined(_LIBUNWIND_TARGET_SPARC) + int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; } +#endif + + bool compactSaysUseDwarf(uint32_t *offset=NULL) const { + R dummy; + return compactSaysUseDwarf(dummy, offset); + } + +#if defined(_LIBUNWIND_TARGET_X86_64) + bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const { + if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) { + if (offset) + *offset = (_info.format & UNWIND_X86_64_DWARF_SECTION_OFFSET); + return true; + } + return false; + } +#endif + +#if defined(_LIBUNWIND_TARGET_I386) + bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const { + if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) { + if (offset) + *offset = (_info.format & UNWIND_X86_DWARF_SECTION_OFFSET); + return true; + } + return false; + } +#endif + +#if defined(_LIBUNWIND_TARGET_PPC) + bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const { + return true; + } +#endif + +#if defined(_LIBUNWIND_TARGET_PPC64) + bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const { + return true; + } +#endif + +#if defined(_LIBUNWIND_TARGET_AARCH64) + bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const { + if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) { + if (offset) + *offset = (_info.format & UNWIND_ARM64_DWARF_SECTION_OFFSET); + return true; + } + return false; + } +#endif + +#if defined(_LIBUNWIND_TARGET_MIPS_O32) + bool compactSaysUseDwarf(Registers_mips_o32 &, uint32_t *) const { + return true; + } +#endif + +#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) + bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const { + return true; + } +#endif + +#if defined(_LIBUNWIND_TARGET_SPARC) + bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; } +#endif + +#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) + +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + compact_unwind_encoding_t dwarfEncoding() const { + R dummy; + return dwarfEncoding(dummy); + } + +#if defined(_LIBUNWIND_TARGET_X86_64) + compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const { + return UNWIND_X86_64_MODE_DWARF; + } +#endif + +#if defined(_LIBUNWIND_TARGET_I386) + compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const { + return UNWIND_X86_MODE_DWARF; + } +#endif + +#if defined(_LIBUNWIND_TARGET_PPC) + compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const { + return 0; + } +#endif + +#if defined(_LIBUNWIND_TARGET_PPC64) + compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const { + return 0; + } +#endif + +#if defined(_LIBUNWIND_TARGET_AARCH64) + compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const { + return UNWIND_ARM64_MODE_DWARF; + } +#endif + +#if defined(_LIBUNWIND_TARGET_ARM) + compact_unwind_encoding_t dwarfEncoding(Registers_arm &) const { + return 0; + } +#endif + +#if defined (_LIBUNWIND_TARGET_OR1K) + compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const { + return 0; + } +#endif + +#if defined (_LIBUNWIND_TARGET_RISCV) + compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const { + return 0; + } +#endif + +#if defined (_LIBUNWIND_TARGET_MIPS_O32) + compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const { + return 0; + } +#endif + +#if defined (_LIBUNWIND_TARGET_MIPS_NEWABI) + compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const { + return 0; + } +#endif + +#if defined(_LIBUNWIND_TARGET_SPARC) + compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; } +#endif + +#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + +#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) + // For runtime environments using SEH unwind data without Windows runtime + // support. + pint_t getLastPC() const { /* FIXME: Implement */ return 0; } + void setLastPC(pint_t pc) { /* FIXME: Implement */ } + RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) { + /* FIXME: Implement */ + *base = 0; + return nullptr; + } + bool getInfoFromSEH(pint_t pc); + int stepWithSEHData() { /* FIXME: Implement */ return 0; } +#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) + + + A &_addressSpace; + R _registers; + unw_proc_info_t _info; + bool _unwindInfoMissing; + bool _isSignalFrame; +}; + + +template +UnwindCursor::UnwindCursor(unw_context_t *context, A &as) + : _addressSpace(as), _registers(context), _unwindInfoMissing(false), + _isSignalFrame(false) { + static_assert((check_fit, unw_cursor_t>::does_fit), + "UnwindCursor<> does not fit in unw_cursor_t"); + memset(&_info, 0, sizeof(_info)); +} + +template +UnwindCursor::UnwindCursor(A &as, void *) + : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) { + memset(&_info, 0, sizeof(_info)); + // FIXME + // fill in _registers from thread arg +} + + +template +bool UnwindCursor::validReg(int regNum) { + return _registers.validRegister(regNum); +} + +template +unw_word_t UnwindCursor::getReg(int regNum) { + return _registers.getRegister(regNum); +} + +template +void UnwindCursor::setReg(int regNum, unw_word_t value) { + _registers.setRegister(regNum, (typename A::pint_t)value); +} + +template +bool UnwindCursor::validFloatReg(int regNum) { + return _registers.validFloatRegister(regNum); +} + +template +unw_fpreg_t UnwindCursor::getFloatReg(int regNum) { + return _registers.getFloatRegister(regNum); +} + +template +void UnwindCursor::setFloatReg(int regNum, unw_fpreg_t value) { + _registers.setFloatRegister(regNum, value); +} + +template void UnwindCursor::jumpto() { + _registers.jumpto(); +} + +#ifdef __arm__ +template void UnwindCursor::saveVFPAsX() { + _registers.saveVFPAsX(); +} +#endif + +template +const char *UnwindCursor::getRegisterName(int regNum) { + return _registers.getRegisterName(regNum); +} + +template bool UnwindCursor::isSignalFrame() { + return _isSignalFrame; +} + +#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) + +#if defined(_LIBUNWIND_ARM_EHABI) +struct EHABIIndexEntry { + uint32_t functionOffset; + uint32_t data; +}; + +template +struct EHABISectionIterator { + typedef EHABISectionIterator _Self; + + typedef std::random_access_iterator_tag iterator_category; + typedef typename A::pint_t value_type; + typedef typename A::pint_t* pointer; + typedef typename A::pint_t& reference; + typedef size_t size_type; + typedef size_t difference_type; + + static _Self begin(A& addressSpace, const UnwindInfoSections& sects) { + return _Self(addressSpace, sects, 0); + } + static _Self end(A& addressSpace, const UnwindInfoSections& sects) { + return _Self(addressSpace, sects, + sects.arm_section_length / sizeof(EHABIIndexEntry)); + } + + EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i) + : _i(i), _addressSpace(&addressSpace), _sects(§s) {} + + _Self& operator++() { ++_i; return *this; } + _Self& operator+=(size_t a) { _i += a; return *this; } + _Self& operator--() { assert(_i > 0); --_i; return *this; } + _Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; } + + _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; } + _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; } + + size_t operator-(const _Self& other) { return _i - other._i; } + + bool operator==(const _Self& other) const { + assert(_addressSpace == other._addressSpace); + assert(_sects == other._sects); + return _i == other._i; + } + + typename A::pint_t operator*() const { return functionAddress(); } + + typename A::pint_t functionAddress() const { + typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof( + EHABIIndexEntry, _i, functionOffset); + return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr)); + } + + typename A::pint_t dataAddress() { + typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof( + EHABIIndexEntry, _i, data); + return indexAddr; + } + + private: + size_t _i; + A* _addressSpace; + const UnwindInfoSections* _sects; +}; + +template +bool UnwindCursor::getInfoFromEHABISection( + pint_t pc, + const UnwindInfoSections §s) { + EHABISectionIterator begin = + EHABISectionIterator::begin(_addressSpace, sects); + EHABISectionIterator end = + EHABISectionIterator::end(_addressSpace, sects); + if (begin == end) + return false; + + EHABISectionIterator itNextPC = std::upper_bound(begin, end, pc); + if (itNextPC == begin) + return false; + EHABISectionIterator itThisPC = itNextPC - 1; + + pint_t thisPC = itThisPC.functionAddress(); + // If an exception is thrown from a function, corresponding to the last entry + // in the table, we don't really know the function extent and have to choose a + // value for nextPC. Choosing max() will allow the range check during trace to + // succeed. + pint_t nextPC = (itNextPC == end) ? std::numeric_limits::max() + : itNextPC.functionAddress(); + pint_t indexDataAddr = itThisPC.dataAddress(); + + if (indexDataAddr == 0) + return false; + + uint32_t indexData = _addressSpace.get32(indexDataAddr); + if (indexData == UNW_EXIDX_CANTUNWIND) + return false; + + // If the high bit is set, the exception handling table entry is inline inside + // the index table entry on the second word (aka |indexDataAddr|). Otherwise, + // the table points at an offset in the exception handling table (section 5 EHABI). + pint_t exceptionTableAddr; + uint32_t exceptionTableData; + bool isSingleWordEHT; + if (indexData & 0x80000000) { + exceptionTableAddr = indexDataAddr; + // TODO(ajwong): Should this data be 0? + exceptionTableData = indexData; + isSingleWordEHT = true; + } else { + exceptionTableAddr = indexDataAddr + signExtendPrel31(indexData); + exceptionTableData = _addressSpace.get32(exceptionTableAddr); + isSingleWordEHT = false; + } + + // Now we know the 3 things: + // exceptionTableAddr -- exception handler table entry. + // exceptionTableData -- the data inside the first word of the eht entry. + // isSingleWordEHT -- whether the entry is in the index. + unw_word_t personalityRoutine = 0xbadf00d; + bool scope32 = false; + uintptr_t lsda; + + // If the high bit in the exception handling table entry is set, the entry is + // in compact form (section 6.3 EHABI). + if (exceptionTableData & 0x80000000) { + // Grab the index of the personality routine from the compact form. + uint32_t choice = (exceptionTableData & 0x0f000000) >> 24; + uint32_t extraWords = 0; + switch (choice) { + case 0: + personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0; + extraWords = 0; + scope32 = false; + lsda = isSingleWordEHT ? 0 : (exceptionTableAddr + 4); + break; + case 1: + personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr1; + extraWords = (exceptionTableData & 0x00ff0000) >> 16; + scope32 = false; + lsda = exceptionTableAddr + (extraWords + 1) * 4; + break; + case 2: + personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr2; + extraWords = (exceptionTableData & 0x00ff0000) >> 16; + scope32 = true; + lsda = exceptionTableAddr + (extraWords + 1) * 4; + break; + default: + _LIBUNWIND_ABORT("unknown personality routine"); + return false; + } + + if (isSingleWordEHT) { + if (extraWords != 0) { + _LIBUNWIND_ABORT("index inlined table detected but pr function " + "requires extra words"); + return false; + } + } + } else { + pint_t personalityAddr = + exceptionTableAddr + signExtendPrel31(exceptionTableData); + personalityRoutine = personalityAddr; + + // ARM EHABI # 6.2, # 9.2 + // + // +---- ehtp + // v + // +--------------------------------------+ + // | +--------+--------+--------+-------+ | + // | |0| prel31 to personalityRoutine | | + // | +--------+--------+--------+-------+ | + // | | N | unwind opcodes | | <-- UnwindData + // | +--------+--------+--------+-------+ | + // | | Word 2 unwind opcodes | | + // | +--------+--------+--------+-------+ | + // | ... | + // | +--------+--------+--------+-------+ | + // | | Word N unwind opcodes | | + // | +--------+--------+--------+-------+ | + // | | LSDA | | <-- lsda + // | | ... | | + // | +--------+--------+--------+-------+ | + // +--------------------------------------+ + + uint32_t *UnwindData = reinterpret_cast(exceptionTableAddr) + 1; + uint32_t FirstDataWord = *UnwindData; + size_t N = ((FirstDataWord >> 24) & 0xff); + size_t NDataWords = N + 1; + lsda = reinterpret_cast(UnwindData + NDataWords); + } + + _info.start_ip = thisPC; + _info.end_ip = nextPC; + _info.handler = personalityRoutine; + _info.unwind_info = exceptionTableAddr; + _info.lsda = lsda; + // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0. + _info.flags = isSingleWordEHT ? 1 : 0 | scope32 ? 0x2 : 0; // Use enum? + + return true; +} +#endif + +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) +template +bool UnwindCursor::getInfoFromDwarfSection(pint_t pc, + const UnwindInfoSections §s, + uint32_t fdeSectionOffsetHint) { + typename CFI_Parser::FDE_Info fdeInfo; + typename CFI_Parser::CIE_Info cieInfo; + bool foundFDE = false; + bool foundInCache = false; + // If compact encoding table gave offset into dwarf section, go directly there + if (fdeSectionOffsetHint != 0) { + foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, + (uint32_t)sects.dwarf_section_length, + sects.dwarf_section + fdeSectionOffsetHint, + &fdeInfo, &cieInfo); + } +#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + if (!foundFDE && (sects.dwarf_index_section != 0)) { + foundFDE = EHHeaderParser::findFDE( + _addressSpace, pc, sects.dwarf_index_section, + (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo); + } +#endif + if (!foundFDE) { + // otherwise, search cache of previously found FDEs. + pint_t cachedFDE = DwarfFDECache::findFDE(sects.dso_base, pc); + if (cachedFDE != 0) { + foundFDE = + CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, + (uint32_t)sects.dwarf_section_length, + cachedFDE, &fdeInfo, &cieInfo); + foundInCache = foundFDE; + } + } + if (!foundFDE) { + // Still not found, do full scan of __eh_frame section. + foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, + (uint32_t)sects.dwarf_section_length, 0, + &fdeInfo, &cieInfo); + } + if (foundFDE) { + typename CFI_Parser::PrologInfo prolog; + if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, + R::getArch(), &prolog)) { + // Save off parsed FDE info + _info.start_ip = fdeInfo.pcStart; + _info.end_ip = fdeInfo.pcEnd; + _info.lsda = fdeInfo.lsda; + _info.handler = cieInfo.personality; + _info.gp = prolog.spExtraArgSize; + _info.flags = 0; + _info.format = dwarfEncoding(); + _info.unwind_info = fdeInfo.fdeStart; + _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; + _info.extra = (unw_word_t) sects.dso_base; + + // Add to cache (to make next lookup faster) if we had no hint + // and there was no index. + if (!foundInCache && (fdeSectionOffsetHint == 0)) { + #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + if (sects.dwarf_index_section == 0) + #endif + DwarfFDECache::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd, + fdeInfo.fdeStart); + } + return true; + } + } + //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc); + return false; +} +#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + + +#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) +template +bool UnwindCursor::getInfoFromCompactEncodingSection(pint_t pc, + const UnwindInfoSections §s) { + const bool log = false; + if (log) + fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n", + (uint64_t)pc, (uint64_t)sects.dso_base); + + const UnwindSectionHeader sectionHeader(_addressSpace, + sects.compact_unwind_section); + if (sectionHeader.version() != UNWIND_SECTION_VERSION) + return false; + + // do a binary search of top level index to find page with unwind info + pint_t targetFunctionOffset = pc - sects.dso_base; + const UnwindSectionIndexArray topIndex(_addressSpace, + sects.compact_unwind_section + + sectionHeader.indexSectionOffset()); + uint32_t low = 0; + uint32_t high = sectionHeader.indexCount(); + uint32_t last = high - 1; + while (low < high) { + uint32_t mid = (low + high) / 2; + //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n", + //mid, low, high, topIndex.functionOffset(mid)); + if (topIndex.functionOffset(mid) <= targetFunctionOffset) { + if ((mid == last) || + (topIndex.functionOffset(mid + 1) > targetFunctionOffset)) { + low = mid; + break; + } else { + low = mid + 1; + } + } else { + high = mid; + } + } + const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low); + const uint32_t firstLevelNextPageFunctionOffset = + topIndex.functionOffset(low + 1); + const pint_t secondLevelAddr = + sects.compact_unwind_section + topIndex.secondLevelPagesSectionOffset(low); + const pint_t lsdaArrayStartAddr = + sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low); + const pint_t lsdaArrayEndAddr = + sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low+1); + if (log) + fprintf(stderr, "\tfirst level search for result index=%d " + "to secondLevelAddr=0x%llX\n", + low, (uint64_t) secondLevelAddr); + // do a binary search of second level page index + uint32_t encoding = 0; + pint_t funcStart = 0; + pint_t funcEnd = 0; + pint_t lsda = 0; + pint_t personality = 0; + uint32_t pageKind = _addressSpace.get32(secondLevelAddr); + if (pageKind == UNWIND_SECOND_LEVEL_REGULAR) { + // regular page + UnwindSectionRegularPageHeader pageHeader(_addressSpace, + secondLevelAddr); + UnwindSectionRegularArray pageIndex( + _addressSpace, secondLevelAddr + pageHeader.entryPageOffset()); + // binary search looks for entry with e where index[e].offset <= pc < + // index[e+1].offset + if (log) + fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in " + "regular page starting at secondLevelAddr=0x%llX\n", + (uint64_t) targetFunctionOffset, (uint64_t) secondLevelAddr); + low = 0; + high = pageHeader.entryCount(); + while (low < high) { + uint32_t mid = (low + high) / 2; + if (pageIndex.functionOffset(mid) <= targetFunctionOffset) { + if (mid == (uint32_t)(pageHeader.entryCount() - 1)) { + // at end of table + low = mid; + funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base; + break; + } else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) { + // next is too big, so we found it + low = mid; + funcEnd = pageIndex.functionOffset(low + 1) + sects.dso_base; + break; + } else { + low = mid + 1; + } + } else { + high = mid; + } + } + encoding = pageIndex.encoding(low); + funcStart = pageIndex.functionOffset(low) + sects.dso_base; + if (pc < funcStart) { + if (log) + fprintf( + stderr, + "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", + (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd); + return false; + } + if (pc > funcEnd) { + if (log) + fprintf( + stderr, + "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", + (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd); + return false; + } + } else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) { + // compressed page + UnwindSectionCompressedPageHeader pageHeader(_addressSpace, + secondLevelAddr); + UnwindSectionCompressedArray pageIndex( + _addressSpace, secondLevelAddr + pageHeader.entryPageOffset()); + const uint32_t targetFunctionPageOffset = + (uint32_t)(targetFunctionOffset - firstLevelFunctionOffset); + // binary search looks for entry with e where index[e].offset <= pc < + // index[e+1].offset + if (log) + fprintf(stderr, "\tbinary search of compressed page starting at " + "secondLevelAddr=0x%llX\n", + (uint64_t) secondLevelAddr); + low = 0; + last = pageHeader.entryCount() - 1; + high = pageHeader.entryCount(); + while (low < high) { + uint32_t mid = (low + high) / 2; + if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) { + if ((mid == last) || + (pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) { + low = mid; + break; + } else { + low = mid + 1; + } + } else { + high = mid; + } + } + funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset + + sects.dso_base; + if (low < last) + funcEnd = + pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset + + sects.dso_base; + else + funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base; + if (pc < funcStart) { + _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " + "level compressed unwind table. funcStart=0x%llX", + (uint64_t) pc, (uint64_t) funcStart); + return false; + } + if (pc > funcEnd) { + _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " + "level compressed unwind table. funcEnd=0x%llX", + (uint64_t) pc, (uint64_t) funcEnd); + return false; + } + uint16_t encodingIndex = pageIndex.encodingIndex(low); + if (encodingIndex < sectionHeader.commonEncodingsArrayCount()) { + // encoding is in common table in section header + encoding = _addressSpace.get32( + sects.compact_unwind_section + + sectionHeader.commonEncodingsArraySectionOffset() + + encodingIndex * sizeof(uint32_t)); + } else { + // encoding is in page specific table + uint16_t pageEncodingIndex = + encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount(); + encoding = _addressSpace.get32(secondLevelAddr + + pageHeader.encodingsPageOffset() + + pageEncodingIndex * sizeof(uint32_t)); + } + } else { + _LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second " + "level page", + (uint64_t) sects.compact_unwind_section); + return false; + } + + // look up LSDA, if encoding says function has one + if (encoding & UNWIND_HAS_LSDA) { + UnwindSectionLsdaArray lsdaIndex(_addressSpace, lsdaArrayStartAddr); + uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base); + low = 0; + high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) / + sizeof(unwind_info_section_header_lsda_index_entry); + // binary search looks for entry with exact match for functionOffset + if (log) + fprintf(stderr, + "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n", + funcStartOffset); + while (low < high) { + uint32_t mid = (low + high) / 2; + if (lsdaIndex.functionOffset(mid) == funcStartOffset) { + lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base; + break; + } else if (lsdaIndex.functionOffset(mid) < funcStartOffset) { + low = mid + 1; + } else { + high = mid; + } + } + if (lsda == 0) { + _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for " + "pc=0x%0llX, but lsda table has no entry", + encoding, (uint64_t) pc); + return false; + } + } + + // extact personality routine, if encoding says function has one + uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >> + (__builtin_ctz(UNWIND_PERSONALITY_MASK)); + if (personalityIndex != 0) { + --personalityIndex; // change 1-based to zero-based index + if (personalityIndex > sectionHeader.personalityArrayCount()) { + _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, " + "but personality table has only %d entires", + encoding, personalityIndex, + sectionHeader.personalityArrayCount()); + return false; + } + int32_t personalityDelta = (int32_t)_addressSpace.get32( + sects.compact_unwind_section + + sectionHeader.personalityArraySectionOffset() + + personalityIndex * sizeof(uint32_t)); + pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta; + personality = _addressSpace.getP(personalityPointer); + if (log) + fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " + "personalityDelta=0x%08X, personality=0x%08llX\n", + (uint64_t) pc, personalityDelta, (uint64_t) personality); + } + + if (log) + fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " + "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n", + (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart); + _info.start_ip = funcStart; + _info.end_ip = funcEnd; + _info.lsda = lsda; + _info.handler = personality; + _info.gp = 0; + _info.flags = 0; + _info.format = encoding; + _info.unwind_info = 0; + _info.unwind_info_size = 0; + _info.extra = sects.dso_base; + return true; +} +#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) + + +#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) +template +bool UnwindCursor::getInfoFromSEH(pint_t pc) { + pint_t base; + RUNTIME_FUNCTION *unwindEntry = lookUpSEHUnwindInfo(pc, &base); + if (!unwindEntry) { + _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc); + return false; + } + _info.gp = 0; + _info.flags = 0; + _info.format = 0; + _info.unwind_info_size = sizeof(RUNTIME_FUNCTION); + _info.unwind_info = reinterpret_cast(unwindEntry); + _info.extra = base; + _info.start_ip = base + unwindEntry->BeginAddress; +#ifdef _LIBUNWIND_TARGET_X86_64 + _info.end_ip = base + unwindEntry->EndAddress; + // Only fill in the handler and LSDA if they're stale. + if (pc != getLastPC()) { + UNWIND_INFO *xdata = reinterpret_cast(base + unwindEntry->UnwindData); + if (xdata->Flags & (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER)) { + // The personality is given in the UNWIND_INFO itself. The LSDA immediately + // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit + // these structures.) + // N.B. UNWIND_INFO structs are DWORD-aligned. + uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1; + const uint32_t *handler = reinterpret_cast(&xdata->UnwindCodes[lastcode]); + _info.lsda = reinterpret_cast(handler+1); + if (*handler) { + _info.handler = reinterpret_cast(__libunwind_seh_personality); + } else + _info.handler = 0; + } else { + _info.lsda = 0; + _info.handler = 0; + } + } +#elif defined(_LIBUNWIND_TARGET_ARM) + _info.end_ip = _info.start_ip + unwindEntry->FunctionLength; + _info.lsda = 0; // FIXME + _info.handler = 0; // FIXME +#endif + setLastPC(pc); + return true; +} +#endif + + +template +void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { + pint_t pc = (pint_t)this->getReg(UNW_REG_IP); +#if defined(_LIBUNWIND_ARM_EHABI) + // Remove the thumb bit so the IP represents the actual instruction address. + // This matches the behaviour of _Unwind_GetIP on arm. + pc &= (pint_t)~0x1; +#endif + + // If the last line of a function is a "throw" the compiler sometimes + // emits no instructions after the call to __cxa_throw. This means + // the return address is actually the start of the next function. + // To disambiguate this, back up the pc when we know it is a return + // address. + if (isReturnAddress) + --pc; + + // Ask address space object to find unwind sections for this pc. + UnwindInfoSections sects; + if (_addressSpace.findUnwindSections(pc, sects)) { +#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) + // If there is a compact unwind encoding table, look there first. + if (sects.compact_unwind_section != 0) { + if (this->getInfoFromCompactEncodingSection(pc, sects)) { + #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + // Found info in table, done unless encoding says to use dwarf. + uint32_t dwarfOffset; + if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) { + if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) { + // found info in dwarf, done + return; + } + } + #endif + // If unwind table has entry, but entry says there is no unwind info, + // record that we have no unwind info. + if (_info.format == 0) + _unwindInfoMissing = true; + return; + } + } +#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) + +#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) + // If there is SEH unwind info, look there next. + if (this->getInfoFromSEH(pc)) + return; +#endif + +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + // If there is dwarf unwind info, look there next. + if (sects.dwarf_section != 0) { + if (this->getInfoFromDwarfSection(pc, sects)) { + // found info in dwarf, done + return; + } + } +#endif + +#if defined(_LIBUNWIND_ARM_EHABI) + // If there is ARM EHABI unwind info, look there next. + if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects)) + return; +#endif + } + +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + // There is no static unwind info for this pc. Look to see if an FDE was + // dynamically registered for it. + pint_t cachedFDE = DwarfFDECache::findFDE(0, pc); + if (cachedFDE != 0) { + CFI_Parser::FDE_Info fdeInfo; + CFI_Parser::CIE_Info cieInfo; + const char *msg = CFI_Parser::decodeFDE(_addressSpace, + cachedFDE, &fdeInfo, &cieInfo); + if (msg == NULL) { + typename CFI_Parser::PrologInfo prolog; + if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, + pc, R::getArch(), &prolog)) { + // save off parsed FDE info + _info.start_ip = fdeInfo.pcStart; + _info.end_ip = fdeInfo.pcEnd; + _info.lsda = fdeInfo.lsda; + _info.handler = cieInfo.personality; + _info.gp = prolog.spExtraArgSize; + // Some frameless functions need SP + // altered when resuming in function. + _info.flags = 0; + _info.format = dwarfEncoding(); + _info.unwind_info = fdeInfo.fdeStart; + _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; + _info.extra = 0; + return; + } + } + } + + // Lastly, ask AddressSpace object about platform specific ways to locate + // other FDEs. + pint_t fde; + if (_addressSpace.findOtherFDE(pc, fde)) { + CFI_Parser::FDE_Info fdeInfo; + CFI_Parser::CIE_Info cieInfo; + if (!CFI_Parser::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) { + // Double check this FDE is for a function that includes the pc. + if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) { + typename CFI_Parser::PrologInfo prolog; + if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, + pc, R::getArch(), &prolog)) { + // save off parsed FDE info + _info.start_ip = fdeInfo.pcStart; + _info.end_ip = fdeInfo.pcEnd; + _info.lsda = fdeInfo.lsda; + _info.handler = cieInfo.personality; + _info.gp = prolog.spExtraArgSize; + _info.flags = 0; + _info.format = dwarfEncoding(); + _info.unwind_info = fdeInfo.fdeStart; + _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; + _info.extra = 0; + return; + } + } + } + } +#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + + // no unwind info, flag that we can't reliably unwind + _unwindInfoMissing = true; +} + +template +int UnwindCursor::step() { + // Bottom of stack is defined is when unwind info cannot be found. + if (_unwindInfoMissing) + return UNW_STEP_END; + + // Use unwinding info to modify register set as if function returned. + int result; +#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) + result = this->stepWithCompactEncoding(); +#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) + result = this->stepWithSEHData(); +#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + result = this->stepWithDwarfFDE(); +#elif defined(_LIBUNWIND_ARM_EHABI) + result = this->stepWithEHABI(); +#else + #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \ + _LIBUNWIND_SUPPORT_SEH_UNWIND or \ + _LIBUNWIND_SUPPORT_DWARF_UNWIND or \ + _LIBUNWIND_ARM_EHABI +#endif + + // update info based on new PC + if (result == UNW_STEP_SUCCESS) { + this->setInfoBasedOnIPRegister(true); + if (_unwindInfoMissing) + return UNW_STEP_END; + } + + return result; +} + +template +void UnwindCursor::getInfo(unw_proc_info_t *info) { + *info = _info; +} + +template +bool UnwindCursor::getFunctionName(char *buf, size_t bufLen, + unw_word_t *offset) { + return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP), + buf, bufLen, offset); +} + +} // namespace libunwind + +#endif // __UNWINDCURSOR_HPP__ Index: head/contrib/libunwind/src/UnwindLevel1-gcc-ext.c =================================================================== --- head/contrib/libunwind/src/UnwindLevel1-gcc-ext.c (nonexistent) +++ head/contrib/libunwind/src/UnwindLevel1-gcc-ext.c (revision 345068) @@ -0,0 +1,362 @@ +//===--------------------- UnwindLevel1-gcc-ext.c -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Implements gcc extensions to the C++ ABI Exception Handling Level 1. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "libunwind_ext.h" +#include "libunwind.h" +#include "Unwind-EHABI.h" +#include "unwind.h" + +#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) + +#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) +#define private_1 private_[0] +#endif + +/// Called by __cxa_rethrow(). +_LIBUNWIND_EXPORT _Unwind_Reason_Code +_Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) { +#if defined(_LIBUNWIND_ARM_EHABI) + _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld", + (void *)exception_object, + (long)exception_object->unwinder_cache.reserved1); +#else + _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%" PRIdPTR, + (void *)exception_object, + (intptr_t)exception_object->private_1); +#endif + +#if defined(_LIBUNWIND_ARM_EHABI) + // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0, + // which is in the same position as private_1 below. + return _Unwind_RaiseException(exception_object); +#else + // If this is non-forced and a stopping place was found, then this is a + // re-throw. + // Call _Unwind_RaiseException() as if this was a new exception + if (exception_object->private_1 == 0) { + return _Unwind_RaiseException(exception_object); + // Will return if there is no catch clause, so that __cxa_rethrow can call + // std::terminate(). + } + + // Call through to _Unwind_Resume() which distiguishes between forced and + // regular exceptions. + _Unwind_Resume(exception_object); + _LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()" + " which unexpectedly returned"); +#endif +} + + +/// Called by personality handler during phase 2 to get base address for data +/// relative encodings. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetDataRelBase(struct _Unwind_Context *context) { + (void)context; + _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context); + _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented"); +} + + +/// Called by personality handler during phase 2 to get base address for text +/// relative encodings. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetTextRelBase(struct _Unwind_Context *context) { + (void)context; + _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", (void *)context); + _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented"); +} + + +/// Scans unwind information to find the function that contains the +/// specified code address "pc". +_LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) { + _LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)", pc); + // This is slow, but works. + // We create an unwind cursor then alter the IP to be pc + unw_cursor_t cursor; + unw_context_t uc; + unw_proc_info_t info; + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t) pc); + if (unw_get_proc_info(&cursor, &info) == UNW_ESUCCESS) + return (void *)(intptr_t) info.start_ip; + else + return NULL; +} + +/// Walk every frame and call trace function at each one. If trace function +/// returns anything other than _URC_NO_REASON, then walk is terminated. +_LIBUNWIND_EXPORT _Unwind_Reason_Code +_Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { + unw_cursor_t cursor; + unw_context_t uc; + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + + _LIBUNWIND_TRACE_API("_Unwind_Backtrace(callback=%p)", + (void *)(uintptr_t)callback); + +#if defined(_LIBUNWIND_ARM_EHABI) + // Create a mock exception object for force unwinding. + _Unwind_Exception ex; + memset(&ex, '\0', sizeof(ex)); + ex.exception_class = 0x434C4E47554E5700; // CLNGUNW\0 +#endif + + // walk each frame + while (true) { + _Unwind_Reason_Code result; + +#if !defined(_LIBUNWIND_ARM_EHABI) + // ask libunwind to get next frame (skip over first frame which is + // _Unwind_Backtrace()) + if (unw_step(&cursor) <= 0) { + _LIBUNWIND_TRACE_UNWINDING(" _backtrace: ended because cursor reached " + "bottom of stack, returning %d", + _URC_END_OF_STACK); + return _URC_END_OF_STACK; + } +#else + // Get the information for this frame. + unw_proc_info_t frameInfo; + if (unw_get_proc_info(&cursor, &frameInfo) != UNW_ESUCCESS) { + return _URC_END_OF_STACK; + } + + // Update the pr_cache in the mock exception object. + const uint32_t* unwindInfo = (uint32_t *) frameInfo.unwind_info; + ex.pr_cache.fnstart = frameInfo.start_ip; + ex.pr_cache.ehtp = (_Unwind_EHT_Header *) unwindInfo; + ex.pr_cache.additional= frameInfo.flags; + + struct _Unwind_Context *context = (struct _Unwind_Context *)&cursor; + // Get and call the personality function to unwind the frame. + __personality_routine handler = (__personality_routine) frameInfo.handler; + if (handler == NULL) { + return _URC_END_OF_STACK; + } + if (handler(_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, &ex, context) != + _URC_CONTINUE_UNWIND) { + return _URC_END_OF_STACK; + } +#endif // defined(_LIBUNWIND_ARM_EHABI) + + // debugging + if (_LIBUNWIND_TRACING_UNWINDING) { + char functionName[512]; + unw_proc_info_t frame; + unw_word_t offset; + unw_get_proc_name(&cursor, functionName, 512, &offset); + unw_get_proc_info(&cursor, &frame); + _LIBUNWIND_TRACE_UNWINDING( + " _backtrace: start_ip=0x%" PRIxPTR ", func=%s, lsda=0x%" PRIxPTR ", context=%p", + frame.start_ip, functionName, frame.lsda, + (void *)&cursor); + } + + // call trace function with this frame + result = (*callback)((struct _Unwind_Context *)(&cursor), ref); + if (result != _URC_NO_REASON) { + _LIBUNWIND_TRACE_UNWINDING( + " _backtrace: ended because callback returned %d", result); + return result; + } + } +} + + +/// Find DWARF unwind info for an address 'pc' in some function. +_LIBUNWIND_EXPORT const void *_Unwind_Find_FDE(const void *pc, + struct dwarf_eh_bases *bases) { + // This is slow, but works. + // We create an unwind cursor then alter the IP to be pc + unw_cursor_t cursor; + unw_context_t uc; + unw_proc_info_t info; + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t) pc); + unw_get_proc_info(&cursor, &info); + bases->tbase = (uintptr_t)info.extra; + bases->dbase = 0; // dbase not used on Mac OS X + bases->func = (uintptr_t)info.start_ip; + _LIBUNWIND_TRACE_API("_Unwind_Find_FDE(pc=%p) => %p", pc, + (void *)(intptr_t) info.unwind_info); + return (void *)(intptr_t) info.unwind_info; +} + +/// Returns the CFA (call frame area, or stack pointer at start of function) +/// for the current context. +_LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { + unw_cursor_t *cursor = (unw_cursor_t *)context; + unw_word_t result; + unw_get_reg(cursor, UNW_REG_SP, &result); + _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p) => 0x%" PRIxPTR, + (void *)context, result); + return (uintptr_t)result; +} + + +/// Called by personality handler during phase 2 to get instruction pointer. +/// ipBefore is a boolean that says if IP is already adjusted to be the call +/// site address. Normally IP is the return address. +_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, + int *ipBefore) { + _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p)", (void *)context); + *ipBefore = 0; + return _Unwind_GetIP(context); +} + +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + +#ifdef __FreeBSD__ + +// Based on LLVM's lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp +// and XXX should be fixed to be alignment-safe. +static void processFDE(const char *addr, bool isDeregister) { + uint64_t length; + while ((length = *((const uint32_t *)addr)) != 0) { + const char *p = addr + 4; + if (length == 0xffffffff) { + length = *((const uint64_t *)p); + p += 8; + } + uint32_t offset = *((const uint32_t *)p); + if (offset != 0) { + if (isDeregister) + _unw_remove_dynamic_fde((unw_word_t)(uintptr_t)addr); + else + _unw_add_dynamic_fde((unw_word_t)(uintptr_t)addr); + } + addr = p + length; + } +} + +/// Called by programs with dynamic code generators that want to register +/// dynamically generated FDEs, with a libgcc-compatible API. + +_LIBUNWIND_EXPORT void __register_frame(const void *addr) { + _LIBUNWIND_TRACE_API("__register_frame(%p)", addr); + processFDE(addr, false); +} + +/// Called by programs with dynamic code generators that want to unregister +/// dynamically generated FDEs, with a libgcc-compatible API. +_LIBUNWIND_EXPORT void __deregister_frame(const void *addr) { + _LIBUNWIND_TRACE_API("__deregister_frame(%p)", addr); + processFDE(addr, true); +} + + +#else + +/// Called by programs with dynamic code generators that want +/// to register a dynamically generated FDE. +/// This function has existed on Mac OS X since 10.4, but +/// was broken until 10.6. +_LIBUNWIND_EXPORT void __register_frame(const void *fde) { + _LIBUNWIND_TRACE_API("__register_frame(%p)", fde); + _unw_add_dynamic_fde((unw_word_t)(uintptr_t) fde); +} + + +/// Called by programs with dynamic code generators that want +/// to unregister a dynamically generated FDE. +/// This function has existed on Mac OS X since 10.4, but +/// was broken until 10.6. +_LIBUNWIND_EXPORT void __deregister_frame(const void *fde) { + _LIBUNWIND_TRACE_API("__deregister_frame(%p)", fde); + _unw_remove_dynamic_fde((unw_word_t)(uintptr_t) fde); +} + +#endif + +// The following register/deregister functions are gcc extensions. +// They have existed on Mac OS X, but have never worked because Mac OS X +// before 10.6 used keymgr to track known FDEs, but these functions +// never got updated to use keymgr. +// For now, we implement these as do-nothing functions to keep any existing +// applications working. We also add the not in 10.6 symbol so that nwe +// application won't be able to use them. + +#if defined(_LIBUNWIND_SUPPORT_FRAME_APIS) +_LIBUNWIND_EXPORT void __register_frame_info_bases(const void *fde, void *ob, + void *tb, void *db) { + (void)fde; + (void)ob; + (void)tb; + (void)db; + _LIBUNWIND_TRACE_API("__register_frame_info_bases(%p,%p, %p, %p)", + fde, ob, tb, db); + // do nothing, this function never worked in Mac OS X +} + +_LIBUNWIND_EXPORT void __register_frame_info(const void *fde, void *ob) { + (void)fde; + (void)ob; + _LIBUNWIND_TRACE_API("__register_frame_info(%p, %p)", fde, ob); + // do nothing, this function never worked in Mac OS X +} + +_LIBUNWIND_EXPORT void __register_frame_info_table_bases(const void *fde, + void *ob, void *tb, + void *db) { + (void)fde; + (void)ob; + (void)tb; + (void)db; + _LIBUNWIND_TRACE_API("__register_frame_info_table_bases" + "(%p,%p, %p, %p)", fde, ob, tb, db); + // do nothing, this function never worked in Mac OS X +} + +_LIBUNWIND_EXPORT void __register_frame_info_table(const void *fde, void *ob) { + (void)fde; + (void)ob; + _LIBUNWIND_TRACE_API("__register_frame_info_table(%p, %p)", fde, ob); + // do nothing, this function never worked in Mac OS X +} + +_LIBUNWIND_EXPORT void __register_frame_table(const void *fde) { + (void)fde; + _LIBUNWIND_TRACE_API("__register_frame_table(%p)", fde); + // do nothing, this function never worked in Mac OS X +} + +_LIBUNWIND_EXPORT void *__deregister_frame_info(const void *fde) { + (void)fde; + _LIBUNWIND_TRACE_API("__deregister_frame_info(%p)", fde); + // do nothing, this function never worked in Mac OS X + return NULL; +} + +_LIBUNWIND_EXPORT void *__deregister_frame_info_bases(const void *fde) { + (void)fde; + _LIBUNWIND_TRACE_API("__deregister_frame_info_bases(%p)", fde); + // do nothing, this function never worked in Mac OS X + return NULL; +} +#endif // defined(_LIBUNWIND_SUPPORT_FRAME_APIS) + +#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + +#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) Property changes on: head/contrib/libunwind/src/UnwindLevel1-gcc-ext.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/UnwindLevel1.c =================================================================== --- head/contrib/libunwind/src/UnwindLevel1.c (nonexistent) +++ head/contrib/libunwind/src/UnwindLevel1.c (revision 345068) @@ -0,0 +1,509 @@ +//===------------------------- UnwindLevel1.c -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Implements C++ ABI Exception Handling Level 1 as documented at: +// http://mentorembedded.github.io/cxx-abi/abi-eh.html +// using libunwind +// +//===----------------------------------------------------------------------===// + +// ARM EHABI does not specify _Unwind_{Get,Set}{GR,IP}(). Thus, we are +// defining inline functions to delegate the function calls to +// _Unwind_VRS_{Get,Set}(). However, some applications might declare the +// function protetype directly (instead of including ), thus we need +// to export these functions from libunwind.so as well. +#define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 1 + +#include +#include +#include +#include +#include +#include + +#include "libunwind.h" +#include "unwind.h" +#include "config.h" + +#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) + +#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND + +static _Unwind_Reason_Code +unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { + unw_init_local(cursor, uc); + + // Walk each frame looking for a place to stop. + bool handlerNotFound = true; + while (handlerNotFound) { + // Ask libunwind to get next frame (skip over first which is + // _Unwind_RaiseException). + int stepResult = unw_step(cursor); + if (stepResult == 0) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached " + "bottom => _URC_END_OF_STACK", + (void *)exception_object); + return _URC_END_OF_STACK; + } else if (stepResult < 0) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => " + "_URC_FATAL_PHASE1_ERROR", + (void *)exception_object); + return _URC_FATAL_PHASE1_ERROR; + } + + // See if frame has code to run (has personality routine). + unw_proc_info_t frameInfo; + unw_word_t sp; + if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info " + "failed => _URC_FATAL_PHASE1_ERROR", + (void *)exception_object); + return _URC_FATAL_PHASE1_ERROR; + } + + // When tracing, print state information. + if (_LIBUNWIND_TRACING_UNWINDING) { + char functionBuf[512]; + const char *functionName = functionBuf; + unw_word_t offset; + if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), + &offset) != UNW_ESUCCESS) || + (frameInfo.start_ip + offset > frameInfo.end_ip)) + functionName = ".anonymous."; + unw_word_t pc; + unw_get_reg(cursor, UNW_REG_IP, &pc); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR + ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "", + (void *)exception_object, pc, frameInfo.start_ip, functionName, + frameInfo.lsda, frameInfo.handler); + } + + // If there is a personality routine, ask it if it will want to stop at + // this frame. + if (frameInfo.handler != 0) { + __personality_routine p = + (__personality_routine)(uintptr_t)(frameInfo.handler); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): calling personality function %p", + (void *)exception_object, (void *)(uintptr_t)p); + _Unwind_Reason_Code personalityResult = + (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class, + exception_object, (struct _Unwind_Context *)(cursor)); + switch (personalityResult) { + case _URC_HANDLER_FOUND: + // found a catch clause or locals that need destructing in this frame + // stop search and remember stack pointer at the frame + handlerNotFound = false; + unw_get_reg(cursor, UNW_REG_SP, &sp); + exception_object->private_2 = (uintptr_t)sp; + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND", + (void *)exception_object); + return _URC_NO_REASON; + + case _URC_CONTINUE_UNWIND: + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND", + (void *)exception_object); + // continue unwinding + break; + + default: + // something went wrong + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR", + (void *)exception_object); + return _URC_FATAL_PHASE1_ERROR; + } + } + } + return _URC_NO_REASON; +} + + +static _Unwind_Reason_Code +unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { + unw_init_local(cursor, uc); + + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", + (void *)exception_object); + + // Walk each frame until we reach where search phase said to stop. + while (true) { + + // Ask libunwind to get next frame (skip over first which is + // _Unwind_RaiseException). + int stepResult = unw_step(cursor); + if (stepResult == 0) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached " + "bottom => _URC_END_OF_STACK", + (void *)exception_object); + return _URC_END_OF_STACK; + } else if (stepResult < 0) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => " + "_URC_FATAL_PHASE1_ERROR", + (void *)exception_object); + return _URC_FATAL_PHASE2_ERROR; + } + + // Get info about this frame. + unw_word_t sp; + unw_proc_info_t frameInfo; + unw_get_reg(cursor, UNW_REG_SP, &sp); + if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info " + "failed => _URC_FATAL_PHASE1_ERROR", + (void *)exception_object); + return _URC_FATAL_PHASE2_ERROR; + } + + // When tracing, print state information. + if (_LIBUNWIND_TRACING_UNWINDING) { + char functionBuf[512]; + const char *functionName = functionBuf; + unw_word_t offset; + if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), + &offset) != UNW_ESUCCESS) || + (frameInfo.start_ip + offset > frameInfo.end_ip)) + functionName = ".anonymous."; + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR + ", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR + ", personality=0x%" PRIxPTR, + (void *)exception_object, frameInfo.start_ip, + functionName, sp, frameInfo.lsda, + frameInfo.handler); + } + + // If there is a personality routine, tell it we are unwinding. + if (frameInfo.handler != 0) { + __personality_routine p = + (__personality_routine)(uintptr_t)(frameInfo.handler); + _Unwind_Action action = _UA_CLEANUP_PHASE; + if (sp == exception_object->private_2) { + // Tell personality this was the frame it marked in phase 1. + action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME); + } + _Unwind_Reason_Code personalityResult = + (*p)(1, action, exception_object->exception_class, exception_object, + (struct _Unwind_Context *)(cursor)); + switch (personalityResult) { + case _URC_CONTINUE_UNWIND: + // Continue unwinding + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND", + (void *)exception_object); + if (sp == exception_object->private_2) { + // Phase 1 said we would stop at this frame, but we did not... + _LIBUNWIND_ABORT("during phase1 personality function said it would " + "stop here, but now in phase2 it did not stop here"); + } + break; + case _URC_INSTALL_CONTEXT: + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT", + (void *)exception_object); + // Personality routine says to transfer control to landing pad. + // We may get control back if landing pad calls _Unwind_Resume(). + if (_LIBUNWIND_TRACING_UNWINDING) { + unw_word_t pc; + unw_get_reg(cursor, UNW_REG_IP, &pc); + unw_get_reg(cursor, UNW_REG_SP, &sp); + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " + "user code with ip=0x%" PRIxPTR + ", sp=0x%" PRIxPTR, + (void *)exception_object, pc, sp); + } + unw_resume(cursor); + // unw_resume() only returns if there was an error. + return _URC_FATAL_PHASE2_ERROR; + default: + // Personality routine returned an unknown result code. + _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", + personalityResult); + return _URC_FATAL_PHASE2_ERROR; + } + } + } + + // Clean up phase did not resume at the frame that the search phase + // said it would... + return _URC_FATAL_PHASE2_ERROR; +} + +static _Unwind_Reason_Code +unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, + _Unwind_Exception *exception_object, + _Unwind_Stop_Fn stop, void *stop_parameter) { + unw_init_local(cursor, uc); + + // Walk each frame until we reach where search phase said to stop + while (unw_step(cursor) > 0) { + + // Update info about this frame. + unw_proc_info_t frameInfo; + if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step " + "failed => _URC_END_OF_STACK", + (void *)exception_object); + return _URC_FATAL_PHASE2_ERROR; + } + + // When tracing, print state information. + if (_LIBUNWIND_TRACING_UNWINDING) { + char functionBuf[512]; + const char *functionName = functionBuf; + unw_word_t offset; + if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), + &offset) != UNW_ESUCCESS) || + (frameInfo.start_ip + offset > frameInfo.end_ip)) + functionName = ".anonymous."; + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR + ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR, + (void *)exception_object, frameInfo.start_ip, functionName, + frameInfo.lsda, frameInfo.handler); + } + + // Call stop function at each frame. + _Unwind_Action action = + (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); + _Unwind_Reason_Code stopResult = + (*stop)(1, action, exception_object->exception_class, exception_object, + (struct _Unwind_Context *)(cursor), stop_parameter); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): stop function returned %d", + (void *)exception_object, stopResult); + if (stopResult != _URC_NO_REASON) { + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): stopped by stop function", + (void *)exception_object); + return _URC_FATAL_PHASE2_ERROR; + } + + // If there is a personality routine, tell it we are unwinding. + if (frameInfo.handler != 0) { + __personality_routine p = + (__personality_routine)(intptr_t)(frameInfo.handler); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", + (void *)exception_object, (void *)(uintptr_t)p); + _Unwind_Reason_Code personalityResult = + (*p)(1, action, exception_object->exception_class, exception_object, + (struct _Unwind_Context *)(cursor)); + switch (personalityResult) { + case _URC_CONTINUE_UNWIND: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned " + "_URC_CONTINUE_UNWIND", + (void *)exception_object); + // Destructors called, continue unwinding + break; + case _URC_INSTALL_CONTEXT: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned " + "_URC_INSTALL_CONTEXT", + (void *)exception_object); + // We may get control back if landing pad calls _Unwind_Resume(). + unw_resume(cursor); + break; + default: + // Personality routine returned an unknown result code. + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned %d, " + "_URC_FATAL_PHASE2_ERROR", + (void *)exception_object, personalityResult); + return _URC_FATAL_PHASE2_ERROR; + } + } + } + + // Call stop function one last time and tell it we've reached the end + // of the stack. + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " + "function with _UA_END_OF_STACK", + (void *)exception_object); + _Unwind_Action lastAction = + (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); + (*stop)(1, lastAction, exception_object->exception_class, exception_object, + (struct _Unwind_Context *)(cursor), stop_parameter); + + // Clean up phase did not resume at the frame that the search phase said it + // would. + return _URC_FATAL_PHASE2_ERROR; +} + + +/// Called by __cxa_throw. Only returns if there is a fatal error. +_LIBUNWIND_EXPORT _Unwind_Reason_Code +_Unwind_RaiseException(_Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)", + (void *)exception_object); + unw_context_t uc; + unw_cursor_t cursor; + unw_getcontext(&uc); + + // Mark that this is a non-forced unwind, so _Unwind_Resume() + // can do the right thing. + exception_object->private_1 = 0; + exception_object->private_2 = 0; + + // phase 1: the search phase + _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object); + if (phase1 != _URC_NO_REASON) + return phase1; + + // phase 2: the clean up phase + return unwind_phase2(&uc, &cursor, exception_object); +} + + + +/// When _Unwind_RaiseException() is in phase2, it hands control +/// to the personality function at each frame. The personality +/// may force a jump to a landing pad in that function, the landing +/// pad code may then call _Unwind_Resume() to continue with the +/// unwinding. Note: the call to _Unwind_Resume() is from compiler +/// geneated user code. All other _Unwind_* routines are called +/// by the C++ runtime __cxa_* routines. +/// +/// Note: re-throwing an exception (as opposed to continuing the unwind) +/// is implemented by having the code call __cxa_rethrow() which +/// in turn calls _Unwind_Resume_or_Rethrow(). +_LIBUNWIND_EXPORT void +_Unwind_Resume(_Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object); + unw_context_t uc; + unw_cursor_t cursor; + unw_getcontext(&uc); + + if (exception_object->private_1 != 0) + unwind_phase2_forced(&uc, &cursor, exception_object, + (_Unwind_Stop_Fn) exception_object->private_1, + (void *)exception_object->private_2); + else + unwind_phase2(&uc, &cursor, exception_object); + + // Clients assume _Unwind_Resume() does not return, so all we can do is abort. + _LIBUNWIND_ABORT("_Unwind_Resume() can't return"); +} + + + +/// Not used by C++. +/// Unwinds stack, calling "stop" function at each frame. +/// Could be used to implement longjmp(). +_LIBUNWIND_EXPORT _Unwind_Reason_Code +_Unwind_ForcedUnwind(_Unwind_Exception *exception_object, + _Unwind_Stop_Fn stop, void *stop_parameter) { + _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)", + (void *)exception_object, (void *)(uintptr_t)stop); + unw_context_t uc; + unw_cursor_t cursor; + unw_getcontext(&uc); + + // Mark that this is a forced unwind, so _Unwind_Resume() can do + // the right thing. + exception_object->private_1 = (uintptr_t) stop; + exception_object->private_2 = (uintptr_t) stop_parameter; + + // do it + return unwind_phase2_forced(&uc, &cursor, exception_object, stop, stop_parameter); +} + + +/// Called by personality handler during phase 2 to get LSDA for current frame. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { + unw_cursor_t *cursor = (unw_cursor_t *)context; + unw_proc_info_t frameInfo; + uintptr_t result = 0; + if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) + result = (uintptr_t)frameInfo.lsda; + _LIBUNWIND_TRACE_API( + "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR, + (void *)context, result); + if (result != 0) { + if (*((uint8_t *)result) != 0xFF) + _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF", + result); + } + return result; +} + + +/// Called by personality handler during phase 2 to find the start of the +/// function. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetRegionStart(struct _Unwind_Context *context) { + unw_cursor_t *cursor = (unw_cursor_t *)context; + unw_proc_info_t frameInfo; + uintptr_t result = 0; + if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) + result = (uintptr_t)frameInfo.start_ip; + _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR, + (void *)context, result); + return result; +} + +#endif // !_LIBUNWIND_SUPPORT_SEH_UNWIND + +/// Called by personality handler during phase 2 if a foreign exception +// is caught. +_LIBUNWIND_EXPORT void +_Unwind_DeleteException(_Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)", + (void *)exception_object); + if (exception_object->exception_cleanup != NULL) + (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, + exception_object); +} + +/// Called by personality handler during phase 2 to get register values. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetGR(struct _Unwind_Context *context, int index) { + unw_cursor_t *cursor = (unw_cursor_t *)context; + unw_word_t result; + unw_get_reg(cursor, index, &result); + _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIxPTR, + (void *)context, index, result); + return (uintptr_t)result; +} + +/// Called by personality handler during phase 2 to alter register values. +_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, + uintptr_t value) { + _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIxPTR + ")", + (void *)context, index, value); + unw_cursor_t *cursor = (unw_cursor_t *)context; + unw_set_reg(cursor, index, value); +} + +/// Called by personality handler during phase 2 to get instruction pointer. +_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { + unw_cursor_t *cursor = (unw_cursor_t *)context; + unw_word_t result; + unw_get_reg(cursor, UNW_REG_IP, &result); + _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR, + (void *)context, result); + return (uintptr_t)result; +} + +/// Called by personality handler during phase 2 to alter instruction pointer, +/// such as setting where the landing pad is, so _Unwind_Resume() will +/// start executing in the landing pad. +_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, + uintptr_t value) { + _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIxPTR ")", + (void *)context, value); + unw_cursor_t *cursor = (unw_cursor_t *)context; + unw_set_reg(cursor, UNW_REG_IP, value); +} + +#endif // !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) Property changes on: head/contrib/libunwind/src/UnwindLevel1.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/UnwindRegistersRestore.S =================================================================== --- head/contrib/libunwind/src/UnwindRegistersRestore.S (nonexistent) +++ head/contrib/libunwind/src/UnwindRegistersRestore.S (revision 345068) @@ -0,0 +1,1111 @@ +//===-------------------- UnwindRegistersRestore.S ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "assembly.h" + + .text + +#if !defined(__USING_SJLJ_EXCEPTIONS__) + +#if defined(__i386__) +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: +# + + +# +-----------------------+ +# + thread_state pointer + +# +-----------------------+ +# + return address + +# +-----------------------+ <-- 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 + movl %edx, 28(%eax) + movl 0(%eax), %ebx + movl %ebx, 0(%edx) + movl 40(%eax), %ebx + movl %ebx, 4(%edx) + # we now have ret and eax pushed onto where new stack will be + # restore all registers + movl 4(%eax), %ebx + movl 8(%eax), %ecx + movl 12(%eax), %edx + movl 16(%eax), %edi + movl 20(%eax), %esi + movl 24(%eax), %ebp + movl 28(%eax), %esp + # skip ss + # skip eflags + pop %eax # eax was already pushed on new stack + ret # eip was already pushed on new stack + # skip cs + # skip ds + # skip es + # skip fs + # skip gs + +#elif defined(__x86_64__) + +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv) +# +# void libunwind::Registers_x86_64::jumpto() +# +#if defined(_WIN64) +# On entry, thread_state pointer is in rcx; move it into rdi +# to share restore code below. Since this routine restores and +# overwrites all registers, we can use the same registers for +# pointers and temporaries as on unix even though win64 normally +# mustn't clobber some of them. + movq %rcx, %rdi +#else +# On entry, thread_state pointer is in rdi +#endif + + movq 56(%rdi), %rax # rax holds new stack pointer + subq $16, %rax + movq %rax, 56(%rdi) + movq 32(%rdi), %rbx # store new rdi on new stack + movq %rbx, 0(%rax) + movq 128(%rdi), %rbx # store new rip on new stack + movq %rbx, 8(%rax) + # restore all registers + movq 0(%rdi), %rax + movq 8(%rdi), %rbx + movq 16(%rdi), %rcx + movq 24(%rdi), %rdx + # restore rdi later + movq 40(%rdi), %rsi + movq 48(%rdi), %rbp + # restore rsp later + movq 64(%rdi), %r8 + movq 72(%rdi), %r9 + movq 80(%rdi), %r10 + movq 88(%rdi), %r11 + movq 96(%rdi), %r12 + movq 104(%rdi), %r13 + movq 112(%rdi), %r14 + movq 120(%rdi), %r15 + # skip rflags + # skip cs + # skip fs + # skip gs + +#if defined(_WIN64) + movdqu 176(%rdi),%xmm0 + movdqu 192(%rdi),%xmm1 + movdqu 208(%rdi),%xmm2 + movdqu 224(%rdi),%xmm3 + movdqu 240(%rdi),%xmm4 + movdqu 256(%rdi),%xmm5 + movdqu 272(%rdi),%xmm6 + movdqu 288(%rdi),%xmm7 + movdqu 304(%rdi),%xmm8 + movdqu 320(%rdi),%xmm9 + movdqu 336(%rdi),%xmm10 + movdqu 352(%rdi),%xmm11 + movdqu 368(%rdi),%xmm12 + movdqu 384(%rdi),%xmm13 + movdqu 400(%rdi),%xmm14 + movdqu 416(%rdi),%xmm15 +#endif + movq 56(%rdi), %rsp # cut back rsp to new location + pop %rdi # rdi was saved here earlier + ret # rip was saved here + + +#elif defined(__powerpc64__) + +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) +// +// void libunwind::Registers_ppc64::jumpto() +// +// On entry: +// thread_state pointer is in r3 +// + +// load register (GPR) +#define PPC64_LR(n) \ + ld %r##n, (8 * (n + 2))(%r3) + + // restore integral registers + // skip r0 for now + // skip r1 for now + PPC64_LR(2) + // skip r3 for now + // skip r4 for now + // skip r5 for now + PPC64_LR(6) + PPC64_LR(7) + PPC64_LR(8) + PPC64_LR(9) + PPC64_LR(10) + PPC64_LR(11) + PPC64_LR(12) + PPC64_LR(13) + PPC64_LR(14) + PPC64_LR(15) + PPC64_LR(16) + PPC64_LR(17) + PPC64_LR(18) + PPC64_LR(19) + PPC64_LR(20) + PPC64_LR(21) + PPC64_LR(22) + PPC64_LR(23) + PPC64_LR(24) + PPC64_LR(25) + PPC64_LR(26) + PPC64_LR(27) + PPC64_LR(28) + PPC64_LR(29) + PPC64_LR(30) + PPC64_LR(31) + +#ifdef PPC64_HAS_VMX + + // restore VS registers + // (note that this also restores floating point registers and V registers, + // because part of VS is mapped to these registers) + + addi %r4, %r3, PPC64_OFFS_FP + +// load VS register +#define PPC64_LVS(n) \ + lxvd2x %vs##n, 0, %r4 ;\ + addi %r4, %r4, 16 + + // restore the first 32 VS regs (and also all floating point regs) + PPC64_LVS(0) + PPC64_LVS(1) + PPC64_LVS(2) + PPC64_LVS(3) + PPC64_LVS(4) + PPC64_LVS(5) + PPC64_LVS(6) + PPC64_LVS(7) + PPC64_LVS(8) + PPC64_LVS(9) + PPC64_LVS(10) + PPC64_LVS(11) + PPC64_LVS(12) + PPC64_LVS(13) + PPC64_LVS(14) + PPC64_LVS(15) + PPC64_LVS(16) + PPC64_LVS(17) + PPC64_LVS(18) + PPC64_LVS(19) + PPC64_LVS(20) + PPC64_LVS(21) + PPC64_LVS(22) + PPC64_LVS(23) + PPC64_LVS(24) + PPC64_LVS(25) + PPC64_LVS(26) + PPC64_LVS(27) + PPC64_LVS(28) + PPC64_LVS(29) + PPC64_LVS(30) + PPC64_LVS(31) + + // use VRSAVE to conditionally restore the remaining VS regs, + // that are where the V regs are mapped + + ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave + cmpwi %r5, 0 + beq Lnovec + +// conditionally load VS +#define PPC64_CLVS_BOTTOM(n) \ + beq Ldone##n ;\ + addi %r4, %r3, PPC64_OFFS_FP + n * 16 ;\ + lxvd2x %vs##n, 0, %r4 ;\ +Ldone##n: + +#define PPC64_CLVSl(n) \ + andis. %r0, %r5, (1<<(47-n)) ;\ +PPC64_CLVS_BOTTOM(n) + +#define PPC64_CLVSh(n) \ + andi. %r0, %r5, (1<<(63-n)) ;\ +PPC64_CLVS_BOTTOM(n) + + PPC64_CLVSl(32) + PPC64_CLVSl(33) + PPC64_CLVSl(34) + PPC64_CLVSl(35) + PPC64_CLVSl(36) + PPC64_CLVSl(37) + PPC64_CLVSl(38) + PPC64_CLVSl(39) + PPC64_CLVSl(40) + PPC64_CLVSl(41) + PPC64_CLVSl(42) + PPC64_CLVSl(43) + PPC64_CLVSl(44) + PPC64_CLVSl(45) + PPC64_CLVSl(46) + PPC64_CLVSl(47) + PPC64_CLVSh(48) + PPC64_CLVSh(49) + PPC64_CLVSh(50) + PPC64_CLVSh(51) + PPC64_CLVSh(52) + PPC64_CLVSh(53) + PPC64_CLVSh(54) + PPC64_CLVSh(55) + PPC64_CLVSh(56) + PPC64_CLVSh(57) + PPC64_CLVSh(58) + PPC64_CLVSh(59) + PPC64_CLVSh(60) + PPC64_CLVSh(61) + PPC64_CLVSh(62) + PPC64_CLVSh(63) + +#else + +// load FP register +#define PPC64_LF(n) \ + lfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3) + + // restore float registers + PPC64_LF(0) + PPC64_LF(1) + PPC64_LF(2) + PPC64_LF(3) + PPC64_LF(4) + PPC64_LF(5) + PPC64_LF(6) + PPC64_LF(7) + PPC64_LF(8) + PPC64_LF(9) + PPC64_LF(10) + PPC64_LF(11) + PPC64_LF(12) + PPC64_LF(13) + PPC64_LF(14) + PPC64_LF(15) + PPC64_LF(16) + PPC64_LF(17) + PPC64_LF(18) + PPC64_LF(19) + PPC64_LF(20) + PPC64_LF(21) + PPC64_LF(22) + PPC64_LF(23) + PPC64_LF(24) + PPC64_LF(25) + PPC64_LF(26) + PPC64_LF(27) + PPC64_LF(28) + PPC64_LF(29) + PPC64_LF(30) + PPC64_LF(31) + + // restore vector registers if any are in use + ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave + cmpwi %r5, 0 + beq Lnovec + + subi %r4, %r1, 16 + // r4 is now a 16-byte aligned pointer into the red zone + // the _vectorScalarRegisters may not be 16-byte aligned + // so copy via red zone temp buffer + +#define PPC64_CLV_UNALIGNED_BOTTOM(n) \ + beq Ldone##n ;\ + ld %r0, (PPC64_OFFS_V + n * 16)(%r3) ;\ + std %r0, 0(%r4) ;\ + ld %r0, (PPC64_OFFS_V + n * 16 + 8)(%r3) ;\ + std %r0, 8(%r4) ;\ + lvx %v##n, 0, %r4 ;\ +Ldone ## n: + +#define PPC64_CLV_UNALIGNEDl(n) \ + andis. %r0, %r5, (1<<(15-n)) ;\ +PPC64_CLV_UNALIGNED_BOTTOM(n) + +#define PPC64_CLV_UNALIGNEDh(n) \ + andi. %r0, %r5, (1<<(31-n)) ;\ +PPC64_CLV_UNALIGNED_BOTTOM(n) + + PPC64_CLV_UNALIGNEDl(0) + PPC64_CLV_UNALIGNEDl(1) + PPC64_CLV_UNALIGNEDl(2) + PPC64_CLV_UNALIGNEDl(3) + PPC64_CLV_UNALIGNEDl(4) + PPC64_CLV_UNALIGNEDl(5) + PPC64_CLV_UNALIGNEDl(6) + PPC64_CLV_UNALIGNEDl(7) + PPC64_CLV_UNALIGNEDl(8) + PPC64_CLV_UNALIGNEDl(9) + PPC64_CLV_UNALIGNEDl(10) + PPC64_CLV_UNALIGNEDl(11) + PPC64_CLV_UNALIGNEDl(12) + PPC64_CLV_UNALIGNEDl(13) + PPC64_CLV_UNALIGNEDl(14) + PPC64_CLV_UNALIGNEDl(15) + PPC64_CLV_UNALIGNEDh(16) + PPC64_CLV_UNALIGNEDh(17) + PPC64_CLV_UNALIGNEDh(18) + PPC64_CLV_UNALIGNEDh(19) + PPC64_CLV_UNALIGNEDh(20) + PPC64_CLV_UNALIGNEDh(21) + PPC64_CLV_UNALIGNEDh(22) + PPC64_CLV_UNALIGNEDh(23) + PPC64_CLV_UNALIGNEDh(24) + PPC64_CLV_UNALIGNEDh(25) + PPC64_CLV_UNALIGNEDh(26) + PPC64_CLV_UNALIGNEDh(27) + PPC64_CLV_UNALIGNEDh(28) + PPC64_CLV_UNALIGNEDh(29) + PPC64_CLV_UNALIGNEDh(30) + PPC64_CLV_UNALIGNEDh(31) + +#endif + +Lnovec: + ld %r0, PPC64_OFFS_CR(%r3) + mtcr %r0 + ld %r0, PPC64_OFFS_SRR0(%r3) + mtctr %r0 + + PPC64_LR(0) + PPC64_LR(5) + PPC64_LR(4) + PPC64_LR(1) + PPC64_LR(3) + bctr + +#elif defined(__ppc__) + +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) +; +; void libunwind::Registers_ppc::jumpto() +; +; On entry: +; thread_state pointer is in r3 +; + + ; restore integral registerrs + ; skip r0 for now + ; skip r1 for now + lwz r2, 16(r3) + ; skip r3 for now + ; skip r4 for now + ; skip r5 for now + lwz r6, 32(r3) + lwz r7, 36(r3) + lwz r8, 40(r3) + lwz r9, 44(r3) + lwz r10, 48(r3) + lwz r11, 52(r3) + lwz r12, 56(r3) + lwz r13, 60(r3) + lwz r14, 64(r3) + lwz r15, 68(r3) + lwz r16, 72(r3) + lwz r17, 76(r3) + lwz r18, 80(r3) + lwz r19, 84(r3) + lwz r20, 88(r3) + lwz r21, 92(r3) + lwz r22, 96(r3) + lwz r23,100(r3) + lwz r24,104(r3) + lwz r25,108(r3) + lwz r26,112(r3) + lwz r27,116(r3) + lwz r28,120(r3) + lwz r29,124(r3) + lwz r30,128(r3) + lwz r31,132(r3) + + ; restore float registers + lfd f0, 160(r3) + lfd f1, 168(r3) + lfd f2, 176(r3) + lfd f3, 184(r3) + lfd f4, 192(r3) + lfd f5, 200(r3) + lfd f6, 208(r3) + lfd f7, 216(r3) + lfd f8, 224(r3) + lfd f9, 232(r3) + lfd f10,240(r3) + lfd f11,248(r3) + lfd f12,256(r3) + lfd f13,264(r3) + lfd f14,272(r3) + lfd f15,280(r3) + lfd f16,288(r3) + lfd f17,296(r3) + lfd f18,304(r3) + lfd f19,312(r3) + lfd f20,320(r3) + lfd f21,328(r3) + lfd f22,336(r3) + lfd f23,344(r3) + lfd f24,352(r3) + lfd f25,360(r3) + lfd f26,368(r3) + lfd f27,376(r3) + lfd f28,384(r3) + lfd f29,392(r3) + lfd f30,400(r3) + lfd f31,408(r3) + + ; restore vector registers if any are in use + lwz r5,156(r3) ; test VRsave + cmpwi r5,0 + beq Lnovec + + subi r4,r1,16 + rlwinm r4,r4,0,0,27 ; mask low 4-bits + ; r4 is now a 16-byte aligned pointer into the red zone + ; the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer + + +#define LOAD_VECTOR_UNALIGNEDl(_index) \ + andis. r0,r5,(1<<(15-_index)) @\ + beq Ldone ## _index @\ + lwz r0, 424+_index*16(r3) @\ + stw r0, 0(r4) @\ + lwz r0, 424+_index*16+4(r3) @\ + stw r0, 4(r4) @\ + lwz r0, 424+_index*16+8(r3) @\ + stw r0, 8(r4) @\ + lwz r0, 424+_index*16+12(r3)@\ + stw r0, 12(r4) @\ + lvx v ## _index,0,r4 @\ +Ldone ## _index: + +#define LOAD_VECTOR_UNALIGNEDh(_index) \ + andi. r0,r5,(1<<(31-_index)) @\ + beq Ldone ## _index @\ + lwz r0, 424+_index*16(r3) @\ + stw r0, 0(r4) @\ + lwz r0, 424+_index*16+4(r3) @\ + stw r0, 4(r4) @\ + lwz r0, 424+_index*16+8(r3) @\ + stw r0, 8(r4) @\ + lwz r0, 424+_index*16+12(r3)@\ + stw r0, 12(r4) @\ + lvx v ## _index,0,r4 @\ + Ldone ## _index: + + + LOAD_VECTOR_UNALIGNEDl(0) + LOAD_VECTOR_UNALIGNEDl(1) + LOAD_VECTOR_UNALIGNEDl(2) + LOAD_VECTOR_UNALIGNEDl(3) + LOAD_VECTOR_UNALIGNEDl(4) + LOAD_VECTOR_UNALIGNEDl(5) + LOAD_VECTOR_UNALIGNEDl(6) + LOAD_VECTOR_UNALIGNEDl(7) + LOAD_VECTOR_UNALIGNEDl(8) + LOAD_VECTOR_UNALIGNEDl(9) + LOAD_VECTOR_UNALIGNEDl(10) + LOAD_VECTOR_UNALIGNEDl(11) + LOAD_VECTOR_UNALIGNEDl(12) + LOAD_VECTOR_UNALIGNEDl(13) + LOAD_VECTOR_UNALIGNEDl(14) + LOAD_VECTOR_UNALIGNEDl(15) + LOAD_VECTOR_UNALIGNEDh(16) + LOAD_VECTOR_UNALIGNEDh(17) + LOAD_VECTOR_UNALIGNEDh(18) + LOAD_VECTOR_UNALIGNEDh(19) + LOAD_VECTOR_UNALIGNEDh(20) + LOAD_VECTOR_UNALIGNEDh(21) + LOAD_VECTOR_UNALIGNEDh(22) + LOAD_VECTOR_UNALIGNEDh(23) + LOAD_VECTOR_UNALIGNEDh(24) + LOAD_VECTOR_UNALIGNEDh(25) + LOAD_VECTOR_UNALIGNEDh(26) + LOAD_VECTOR_UNALIGNEDh(27) + LOAD_VECTOR_UNALIGNEDh(28) + LOAD_VECTOR_UNALIGNEDh(29) + LOAD_VECTOR_UNALIGNEDh(30) + LOAD_VECTOR_UNALIGNEDh(31) + +Lnovec: + lwz r0, 136(r3) ; __cr + mtocrf 255,r0 + lwz r0, 148(r3) ; __ctr + mtctr r0 + lwz r0, 0(r3) ; __ssr0 + mtctr r0 + lwz r0, 8(r3) ; do r0 now + lwz r5,28(r3) ; do r5 now + lwz r4,24(r3) ; do r4 now + lwz r1,12(r3) ; do sp now + lwz r3,20(r3) ; do r3 last + bctr + +#elif defined(__arm64__) || defined(__aarch64__) + +// +// void libunwind::Registers_arm64::jumpto() +// +// On entry: +// thread_state pointer is in x0 +// + .p2align 2 +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) + // skip restore of x0,x1 for now + ldp x2, x3, [x0, #0x010] + ldp x4, x5, [x0, #0x020] + ldp x6, x7, [x0, #0x030] + ldp x8, x9, [x0, #0x040] + ldp x10,x11, [x0, #0x050] + ldp x12,x13, [x0, #0x060] + ldp x14,x15, [x0, #0x070] + ldp x16,x17, [x0, #0x080] + ldp x18,x19, [x0, #0x090] + ldp x20,x21, [x0, #0x0A0] + ldp x22,x23, [x0, #0x0B0] + ldp x24,x25, [x0, #0x0C0] + ldp x26,x27, [x0, #0x0D0] + ldp x28,x29, [x0, #0x0E0] + ldr x30, [x0, #0x100] // restore pc into lr + ldr x1, [x0, #0x0F8] + mov sp,x1 // restore sp + + ldp d0, d1, [x0, #0x110] + ldp d2, d3, [x0, #0x120] + ldp d4, d5, [x0, #0x130] + ldp d6, d7, [x0, #0x140] + ldp d8, d9, [x0, #0x150] + ldp d10,d11, [x0, #0x160] + ldp d12,d13, [x0, #0x170] + ldp d14,d15, [x0, #0x180] + ldp d16,d17, [x0, #0x190] + ldp d18,d19, [x0, #0x1A0] + ldp d20,d21, [x0, #0x1B0] + ldp d22,d23, [x0, #0x1C0] + ldp d24,d25, [x0, #0x1D0] + ldp d26,d27, [x0, #0x1E0] + ldp d28,d29, [x0, #0x1F0] + ldr d30, [x0, #0x200] + ldr d31, [x0, #0x208] + + ldp x0, x1, [x0, #0x000] // restore x0,x1 + ret x30 // jump to pc + +#elif defined(__arm__) && !defined(__APPLE__) + +#if !defined(__ARM_ARCH_ISA_ARM) + .thumb +#endif + +@ +@ void libunwind::Registers_arm::restoreCoreAndJumpTo() +@ +@ On entry: +@ thread_state pointer is in r0 +@ + .p2align 2 +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv) +#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1 + @ r8-r11: ldm into r1-r4, then mov to r8-r11 + adds r0, #0x20 + ldm r0!, {r1-r4} + subs r0, #0x30 + mov r8, r1 + mov r9, r2 + mov r10, r3 + mov r11, r4 + @ r12 does not need loading, it it the intra-procedure-call scratch register + ldr r2, [r0, #0x34] + ldr r3, [r0, #0x3c] + mov sp, r2 + mov lr, r3 @ restore pc into lr + ldm r0, {r0-r7} +#else + @ Use lr as base so that r0 can be restored. + mov lr, r0 + @ 32bit thumb-2 restrictions for ldm: + @ . the sp (r13) cannot be in the list + @ . the pc (r15) and lr (r14) cannot both be in the list in an LDM instruction + ldm lr, {r0-r12} + ldr sp, [lr, #52] + ldr lr, [lr, #60] @ restore pc into lr +#endif + JMP(lr) + +@ +@ static void libunwind::Registers_arm::restoreVFPWithFLDMD(unw_fpreg_t* values) +@ +@ On entry: +@ values pointer is in r0 +@ + .p2align 2 +#if defined(__ELF__) + .fpu vfpv3-d16 +#endif +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPy) + @ VFP and iwMMX instructions are only available when compiling with the flags + @ that enable them. We do not want to do that in the library (because we do not + @ want the compiler to generate instructions that access those) but this is + @ only accessed if the personality routine needs these registers. Use of + @ these registers implies they are, actually, available on the target, so + @ it's ok to execute. + @ So, generate the instruction using the corresponding coprocessor mnemonic. + vldmia r0, {d0-d15} + JMP(lr) + +@ +@ static void libunwind::Registers_arm::restoreVFPWithFLDMX(unw_fpreg_t* values) +@ +@ On entry: +@ values pointer is in r0 +@ + .p2align 2 +#if defined(__ELF__) + .fpu vfpv3-d16 +#endif +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPy) + vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia + JMP(lr) + +@ +@ static void libunwind::Registers_arm::restoreVFPv3(unw_fpreg_t* values) +@ +@ On entry: +@ values pointer is in r0 +@ + .p2align 2 +#if defined(__ELF__) + .fpu vfpv3 +#endif +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy) + vldmia r0, {d16-d31} + JMP(lr) + +#if defined(__ARM_WMMX) + +@ +@ static void libunwind::Registers_arm::restoreiWMMX(unw_fpreg_t* values) +@ +@ On entry: +@ values pointer is in r0 +@ + .p2align 2 +#if defined(__ELF__) + .arch armv5te +#endif +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy) + ldcl p1, cr0, [r0], #8 @ wldrd wR0, [r0], #8 + ldcl p1, cr1, [r0], #8 @ wldrd wR1, [r0], #8 + ldcl p1, cr2, [r0], #8 @ wldrd wR2, [r0], #8 + ldcl p1, cr3, [r0], #8 @ wldrd wR3, [r0], #8 + ldcl p1, cr4, [r0], #8 @ wldrd wR4, [r0], #8 + ldcl p1, cr5, [r0], #8 @ wldrd wR5, [r0], #8 + ldcl p1, cr6, [r0], #8 @ wldrd wR6, [r0], #8 + ldcl p1, cr7, [r0], #8 @ wldrd wR7, [r0], #8 + ldcl p1, cr8, [r0], #8 @ wldrd wR8, [r0], #8 + ldcl p1, cr9, [r0], #8 @ wldrd wR9, [r0], #8 + ldcl p1, cr10, [r0], #8 @ wldrd wR10, [r0], #8 + ldcl p1, cr11, [r0], #8 @ wldrd wR11, [r0], #8 + ldcl p1, cr12, [r0], #8 @ wldrd wR12, [r0], #8 + ldcl p1, cr13, [r0], #8 @ wldrd wR13, [r0], #8 + ldcl p1, cr14, [r0], #8 @ wldrd wR14, [r0], #8 + ldcl p1, cr15, [r0], #8 @ wldrd wR15, [r0], #8 + JMP(lr) + +@ +@ static void libunwind::Registers_arm::restoreiWMMXControl(unw_uint32_t* values) +@ +@ On entry: +@ values pointer is in r0 +@ + .p2align 2 +#if defined(__ELF__) + .arch armv5te +#endif +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj) + ldc2 p1, cr8, [r0], #4 @ wldrw wCGR0, [r0], #4 + ldc2 p1, cr9, [r0], #4 @ wldrw wCGR1, [r0], #4 + ldc2 p1, cr10, [r0], #4 @ wldrw wCGR2, [r0], #4 + ldc2 p1, cr11, [r0], #4 @ wldrw wCGR3, [r0], #4 + JMP(lr) + +#endif + +#elif defined(__or1k__) + +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) +# +# void libunwind::Registers_or1k::jumpto() +# +# On entry: +# thread_state pointer is in r3 +# + + # restore integral registers + l.lwz r0, 0(r3) + l.lwz r1, 4(r3) + l.lwz r2, 8(r3) + # skip r3 for now + l.lwz r4, 16(r3) + l.lwz r5, 20(r3) + l.lwz r6, 24(r3) + l.lwz r7, 28(r3) + l.lwz r8, 32(r3) + # skip r9 + l.lwz r10, 40(r3) + l.lwz r11, 44(r3) + l.lwz r12, 48(r3) + l.lwz r13, 52(r3) + l.lwz r14, 56(r3) + l.lwz r15, 60(r3) + l.lwz r16, 64(r3) + l.lwz r17, 68(r3) + l.lwz r18, 72(r3) + l.lwz r19, 76(r3) + l.lwz r20, 80(r3) + l.lwz r21, 84(r3) + l.lwz r22, 88(r3) + l.lwz r23, 92(r3) + l.lwz r24, 96(r3) + l.lwz r25,100(r3) + l.lwz r26,104(r3) + l.lwz r27,108(r3) + l.lwz r28,112(r3) + l.lwz r29,116(r3) + l.lwz r30,120(r3) + l.lwz r31,124(r3) + + # at last, restore r3 + l.lwz r3, 12(r3) + + # load new pc into ra + l.lwz r9, 128(r3) + # jump to pc + l.jr r9 + l.nop + +#elif defined(__riscv) + +// +// void libunwind::Registers_riscv::jumpto() +// +// On entry: +// thread_state pointer is in a0 +// + .p2align 2 +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) +#ifdef __riscv_float_abi_double + fld f0, (8 * 32 + 8 * 0)(a0) + fld f1, (8 * 32 + 8 * 1)(a0) + fld f2, (8 * 32 + 8 * 2)(a0) + fld f3, (8 * 32 + 8 * 3)(a0) + fld f4, (8 * 32 + 8 * 4)(a0) + fld f5, (8 * 32 + 8 * 5)(a0) + fld f6, (8 * 32 + 8 * 6)(a0) + fld f7, (8 * 32 + 8 * 7)(a0) + fld f8, (8 * 32 + 8 * 8)(a0) + fld f9, (8 * 32 + 8 * 9)(a0) + fld f10, (8 * 32 + 8 * 10)(a0) + fld f11, (8 * 32 + 8 * 11)(a0) + fld f12, (8 * 32 + 8 * 12)(a0) + fld f13, (8 * 32 + 8 * 13)(a0) + fld f14, (8 * 32 + 8 * 14)(a0) + fld f15, (8 * 32 + 8 * 15)(a0) + fld f16, (8 * 32 + 8 * 16)(a0) + fld f17, (8 * 32 + 8 * 17)(a0) + fld f18, (8 * 32 + 8 * 18)(a0) + fld f19, (8 * 32 + 8 * 19)(a0) + fld f20, (8 * 32 + 8 * 20)(a0) + fld f21, (8 * 32 + 8 * 21)(a0) + fld f22, (8 * 32 + 8 * 22)(a0) + fld f23, (8 * 32 + 8 * 23)(a0) + fld f24, (8 * 32 + 8 * 24)(a0) + fld f25, (8 * 32 + 8 * 25)(a0) + fld f26, (8 * 32 + 8 * 26)(a0) + fld f27, (8 * 32 + 8 * 27)(a0) + fld f28, (8 * 32 + 8 * 28)(a0) + fld f29, (8 * 32 + 8 * 29)(a0) + fld f30, (8 * 32 + 8 * 30)(a0) + fld f31, (8 * 32 + 8 * 31)(a0) +#endif + + // x0 is zero + ld x1, (8 * 1)(a0) + ld x2, (8 * 2)(a0) + ld x3, (8 * 3)(a0) + ld x4, (8 * 4)(a0) + ld x5, (8 * 5)(a0) + ld x6, (8 * 6)(a0) + ld x7, (8 * 7)(a0) + ld x8, (8 * 8)(a0) + ld x9, (8 * 9)(a0) + // skip a0 for now + ld x11, (8 * 11)(a0) + ld x12, (8 * 12)(a0) + ld x13, (8 * 13)(a0) + ld x14, (8 * 14)(a0) + ld x15, (8 * 15)(a0) + ld x16, (8 * 16)(a0) + ld x17, (8 * 17)(a0) + ld x18, (8 * 18)(a0) + ld x19, (8 * 19)(a0) + ld x20, (8 * 20)(a0) + ld x21, (8 * 21)(a0) + ld x22, (8 * 22)(a0) + ld x23, (8 * 23)(a0) + ld x24, (8 * 24)(a0) + ld x25, (8 * 25)(a0) + ld x26, (8 * 26)(a0) + ld x27, (8 * 27)(a0) + ld x28, (8 * 28)(a0) + ld x29, (8 * 29)(a0) + ld x30, (8 * 30)(a0) + ld x31, (8 * 31)(a0) + ld x10, (8 * 10)(a0) // restore a0 + + ret // jump to ra + +#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 + +// +// void libunwind::Registers_mips_o32::jumpto() +// +// On entry: +// thread state pointer is in a0 ($4) +// +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) + .set push + .set noat + .set noreorder + .set nomacro +#ifdef __mips_hard_float +#if __mips_fpr != 64 + ldc1 $f0, (4 * 36 + 8 * 0)($4) + ldc1 $f2, (4 * 36 + 8 * 2)($4) + ldc1 $f4, (4 * 36 + 8 * 4)($4) + ldc1 $f6, (4 * 36 + 8 * 6)($4) + ldc1 $f8, (4 * 36 + 8 * 8)($4) + ldc1 $f10, (4 * 36 + 8 * 10)($4) + ldc1 $f12, (4 * 36 + 8 * 12)($4) + ldc1 $f14, (4 * 36 + 8 * 14)($4) + ldc1 $f16, (4 * 36 + 8 * 16)($4) + ldc1 $f18, (4 * 36 + 8 * 18)($4) + ldc1 $f20, (4 * 36 + 8 * 20)($4) + ldc1 $f22, (4 * 36 + 8 * 22)($4) + ldc1 $f24, (4 * 36 + 8 * 24)($4) + ldc1 $f26, (4 * 36 + 8 * 26)($4) + ldc1 $f28, (4 * 36 + 8 * 28)($4) + ldc1 $f30, (4 * 36 + 8 * 30)($4) +#else + ldc1 $f0, (4 * 36 + 8 * 0)($4) + ldc1 $f1, (4 * 36 + 8 * 1)($4) + ldc1 $f2, (4 * 36 + 8 * 2)($4) + ldc1 $f3, (4 * 36 + 8 * 3)($4) + ldc1 $f4, (4 * 36 + 8 * 4)($4) + ldc1 $f5, (4 * 36 + 8 * 5)($4) + ldc1 $f6, (4 * 36 + 8 * 6)($4) + ldc1 $f7, (4 * 36 + 8 * 7)($4) + ldc1 $f8, (4 * 36 + 8 * 8)($4) + ldc1 $f9, (4 * 36 + 8 * 9)($4) + ldc1 $f10, (4 * 36 + 8 * 10)($4) + ldc1 $f11, (4 * 36 + 8 * 11)($4) + ldc1 $f12, (4 * 36 + 8 * 12)($4) + ldc1 $f13, (4 * 36 + 8 * 13)($4) + ldc1 $f14, (4 * 36 + 8 * 14)($4) + ldc1 $f15, (4 * 36 + 8 * 15)($4) + ldc1 $f16, (4 * 36 + 8 * 16)($4) + ldc1 $f17, (4 * 36 + 8 * 17)($4) + ldc1 $f18, (4 * 36 + 8 * 18)($4) + ldc1 $f19, (4 * 36 + 8 * 19)($4) + ldc1 $f20, (4 * 36 + 8 * 20)($4) + ldc1 $f21, (4 * 36 + 8 * 21)($4) + ldc1 $f22, (4 * 36 + 8 * 22)($4) + ldc1 $f23, (4 * 36 + 8 * 23)($4) + ldc1 $f24, (4 * 36 + 8 * 24)($4) + ldc1 $f25, (4 * 36 + 8 * 25)($4) + ldc1 $f26, (4 * 36 + 8 * 26)($4) + ldc1 $f27, (4 * 36 + 8 * 27)($4) + ldc1 $f28, (4 * 36 + 8 * 28)($4) + ldc1 $f29, (4 * 36 + 8 * 29)($4) + ldc1 $f30, (4 * 36 + 8 * 30)($4) + ldc1 $f31, (4 * 36 + 8 * 31)($4) +#endif +#endif + // restore hi and lo + lw $8, (4 * 33)($4) + mthi $8 + lw $8, (4 * 34)($4) + mtlo $8 + // r0 is zero + lw $1, (4 * 1)($4) + lw $2, (4 * 2)($4) + lw $3, (4 * 3)($4) + // skip a0 for now + lw $5, (4 * 5)($4) + lw $6, (4 * 6)($4) + lw $7, (4 * 7)($4) + lw $8, (4 * 8)($4) + lw $9, (4 * 9)($4) + lw $10, (4 * 10)($4) + lw $11, (4 * 11)($4) + lw $12, (4 * 12)($4) + lw $13, (4 * 13)($4) + lw $14, (4 * 14)($4) + lw $15, (4 * 15)($4) + lw $16, (4 * 16)($4) + lw $17, (4 * 17)($4) + lw $18, (4 * 18)($4) + lw $19, (4 * 19)($4) + lw $20, (4 * 20)($4) + lw $21, (4 * 21)($4) + lw $22, (4 * 22)($4) + lw $23, (4 * 23)($4) + lw $24, (4 * 24)($4) + lw $25, (4 * 25)($4) + lw $26, (4 * 26)($4) + lw $27, (4 * 27)($4) + lw $28, (4 * 28)($4) + lw $29, (4 * 29)($4) + lw $30, (4 * 30)($4) + // load new pc into ra + lw $31, (4 * 32)($4) + // jump to ra, load a0 in the delay slot + jr $31 + lw $4, (4 * 4)($4) + .set pop + +#elif defined(__mips64) + +// +// void libunwind::Registers_mips_newabi::jumpto() +// +// On entry: +// thread state pointer is in a0 ($4) +// +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) + .set push + .set noat + .set noreorder + .set nomacro +#ifdef __mips_hard_float + ldc1 $f0, (8 * 35)($4) + ldc1 $f1, (8 * 36)($4) + ldc1 $f2, (8 * 37)($4) + ldc1 $f3, (8 * 38)($4) + ldc1 $f4, (8 * 39)($4) + ldc1 $f5, (8 * 40)($4) + ldc1 $f6, (8 * 41)($4) + ldc1 $f7, (8 * 42)($4) + ldc1 $f8, (8 * 43)($4) + ldc1 $f9, (8 * 44)($4) + ldc1 $f10, (8 * 45)($4) + ldc1 $f11, (8 * 46)($4) + ldc1 $f12, (8 * 47)($4) + ldc1 $f13, (8 * 48)($4) + ldc1 $f14, (8 * 49)($4) + ldc1 $f15, (8 * 50)($4) + ldc1 $f16, (8 * 51)($4) + ldc1 $f17, (8 * 52)($4) + ldc1 $f18, (8 * 53)($4) + ldc1 $f19, (8 * 54)($4) + ldc1 $f20, (8 * 55)($4) + ldc1 $f21, (8 * 56)($4) + ldc1 $f22, (8 * 57)($4) + ldc1 $f23, (8 * 58)($4) + ldc1 $f24, (8 * 59)($4) + ldc1 $f25, (8 * 60)($4) + ldc1 $f26, (8 * 61)($4) + ldc1 $f27, (8 * 62)($4) + ldc1 $f28, (8 * 63)($4) + ldc1 $f29, (8 * 64)($4) + ldc1 $f30, (8 * 65)($4) + ldc1 $f31, (8 * 66)($4) +#endif + // restore hi and lo + ld $8, (8 * 33)($4) + mthi $8 + ld $8, (8 * 34)($4) + mtlo $8 + // r0 is zero + ld $1, (8 * 1)($4) + ld $2, (8 * 2)($4) + ld $3, (8 * 3)($4) + // skip a0 for now + ld $5, (8 * 5)($4) + ld $6, (8 * 6)($4) + ld $7, (8 * 7)($4) + ld $8, (8 * 8)($4) + ld $9, (8 * 9)($4) + ld $10, (8 * 10)($4) + ld $11, (8 * 11)($4) + ld $12, (8 * 12)($4) + ld $13, (8 * 13)($4) + ld $14, (8 * 14)($4) + ld $15, (8 * 15)($4) + ld $16, (8 * 16)($4) + ld $17, (8 * 17)($4) + ld $18, (8 * 18)($4) + ld $19, (8 * 19)($4) + ld $20, (8 * 20)($4) + ld $21, (8 * 21)($4) + ld $22, (8 * 22)($4) + ld $23, (8 * 23)($4) + ld $24, (8 * 24)($4) + ld $25, (8 * 25)($4) + ld $26, (8 * 26)($4) + ld $27, (8 * 27)($4) + ld $28, (8 * 28)($4) + ld $29, (8 * 29)($4) + ld $30, (8 * 30)($4) + // load new pc into ra + ld $31, (8 * 32)($4) + // jump to ra, load a0 in the delay slot + jr $31 + ld $4, (8 * 4)($4) + .set pop + +#elif defined(__sparc__) + +// +// void libunwind::Registers_sparc_o32::jumpto() +// +// On entry: +// thread_state pointer is in o0 +// +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv) + ta 3 + ldd [%o0 + 64], %l0 + ldd [%o0 + 72], %l2 + ldd [%o0 + 80], %l4 + ldd [%o0 + 88], %l6 + ldd [%o0 + 96], %i0 + ldd [%o0 + 104], %i2 + ldd [%o0 + 112], %i4 + ldd [%o0 + 120], %i6 + ld [%o0 + 60], %o7 + jmp %o7 + nop + +#endif + +#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ + +NO_EXEC_STACK_DIRECTIVE + Property changes on: head/contrib/libunwind/src/UnwindRegistersRestore.S ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/UnwindRegistersSave.S =================================================================== --- head/contrib/libunwind/src/UnwindRegistersSave.S (nonexistent) +++ head/contrib/libunwind/src/UnwindRegistersSave.S (revision 345068) @@ -0,0 +1,1058 @@ +//===------------------------ UnwindRegistersSave.S -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "assembly.h" + + .text + +#if !defined(__USING_SJLJ_EXCEPTIONS__) + +#if defined(__i386__) + +# +# extern int unw_getcontext(unw_context_t* thread_state) +# +# On entry: +# + + +# +-----------------------+ +# + thread_state pointer + +# +-----------------------+ +# + return address + +# +-----------------------+ <-- SP +# + + +# +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + push %eax + movl 8(%esp), %eax + movl %ebx, 4(%eax) + movl %ecx, 8(%eax) + movl %edx, 12(%eax) + movl %edi, 16(%eax) + movl %esi, 20(%eax) + movl %ebp, 24(%eax) + movl %esp, %edx + addl $8, %edx + movl %edx, 28(%eax) # store what sp was at call site as esp + # skip ss + # skip eflags + movl 4(%esp), %edx + movl %edx, 40(%eax) # store return address as eip + # skip cs + # skip ds + # skip es + # skip fs + # skip gs + movl (%esp), %edx + movl %edx, (%eax) # store original eax + popl %eax + xorl %eax, %eax # return UNW_ESUCCESS + ret + +#elif defined(__x86_64__) + +# +# extern int unw_getcontext(unw_context_t* thread_state) +# +# On entry: +# thread_state pointer is in rdi +# +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) +#if defined(_WIN64) +#define PTR %rcx +#define TMP %rdx +#else +#define PTR %rdi +#define TMP %rsi +#endif + + movq %rax, (PTR) + movq %rbx, 8(PTR) + movq %rcx, 16(PTR) + movq %rdx, 24(PTR) + movq %rdi, 32(PTR) + movq %rsi, 40(PTR) + movq %rbp, 48(PTR) + movq %rsp, 56(PTR) + addq $8, 56(PTR) + movq %r8, 64(PTR) + movq %r9, 72(PTR) + movq %r10, 80(PTR) + movq %r11, 88(PTR) + movq %r12, 96(PTR) + movq %r13,104(PTR) + movq %r14,112(PTR) + movq %r15,120(PTR) + movq (%rsp),TMP + movq TMP,128(PTR) # store return address as rip + # skip rflags + # skip cs + # skip fs + # skip gs + +#if defined(_WIN64) + movdqu %xmm0,176(PTR) + movdqu %xmm1,192(PTR) + movdqu %xmm2,208(PTR) + movdqu %xmm3,224(PTR) + movdqu %xmm4,240(PTR) + movdqu %xmm5,256(PTR) + movdqu %xmm6,272(PTR) + movdqu %xmm7,288(PTR) + movdqu %xmm8,304(PTR) + movdqu %xmm9,320(PTR) + movdqu %xmm10,336(PTR) + movdqu %xmm11,352(PTR) + movdqu %xmm12,368(PTR) + movdqu %xmm13,384(PTR) + movdqu %xmm14,400(PTR) + movdqu %xmm15,416(PTR) +#endif + xorl %eax, %eax # return UNW_ESUCCESS + ret + +#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 + +# +# extern int unw_getcontext(unw_context_t* thread_state) +# +# On entry: +# thread_state pointer is in a0 ($4) +# +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + .set push + .set noat + .set noreorder + .set nomacro + sw $1, (4 * 1)($4) + sw $2, (4 * 2)($4) + sw $3, (4 * 3)($4) + sw $4, (4 * 4)($4) + sw $5, (4 * 5)($4) + sw $6, (4 * 6)($4) + sw $7, (4 * 7)($4) + sw $8, (4 * 8)($4) + sw $9, (4 * 9)($4) + sw $10, (4 * 10)($4) + sw $11, (4 * 11)($4) + sw $12, (4 * 12)($4) + sw $13, (4 * 13)($4) + sw $14, (4 * 14)($4) + sw $15, (4 * 15)($4) + sw $16, (4 * 16)($4) + sw $17, (4 * 17)($4) + sw $18, (4 * 18)($4) + sw $19, (4 * 19)($4) + sw $20, (4 * 20)($4) + sw $21, (4 * 21)($4) + sw $22, (4 * 22)($4) + sw $23, (4 * 23)($4) + sw $24, (4 * 24)($4) + sw $25, (4 * 25)($4) + sw $26, (4 * 26)($4) + sw $27, (4 * 27)($4) + sw $28, (4 * 28)($4) + sw $29, (4 * 29)($4) + sw $30, (4 * 30)($4) + sw $31, (4 * 31)($4) + # Store return address to pc + sw $31, (4 * 32)($4) + # hi and lo + mfhi $8 + sw $8, (4 * 33)($4) + mflo $8 + sw $8, (4 * 34)($4) +#ifdef __mips_hard_float +#if __mips_fpr != 64 + sdc1 $f0, (4 * 36 + 8 * 0)($4) + sdc1 $f2, (4 * 36 + 8 * 2)($4) + sdc1 $f4, (4 * 36 + 8 * 4)($4) + sdc1 $f6, (4 * 36 + 8 * 6)($4) + sdc1 $f8, (4 * 36 + 8 * 8)($4) + sdc1 $f10, (4 * 36 + 8 * 10)($4) + sdc1 $f12, (4 * 36 + 8 * 12)($4) + sdc1 $f14, (4 * 36 + 8 * 14)($4) + sdc1 $f16, (4 * 36 + 8 * 16)($4) + sdc1 $f18, (4 * 36 + 8 * 18)($4) + sdc1 $f20, (4 * 36 + 8 * 20)($4) + sdc1 $f22, (4 * 36 + 8 * 22)($4) + sdc1 $f24, (4 * 36 + 8 * 24)($4) + sdc1 $f26, (4 * 36 + 8 * 26)($4) + sdc1 $f28, (4 * 36 + 8 * 28)($4) + sdc1 $f30, (4 * 36 + 8 * 30)($4) +#else + sdc1 $f0, (4 * 36 + 8 * 0)($4) + sdc1 $f1, (4 * 36 + 8 * 1)($4) + sdc1 $f2, (4 * 36 + 8 * 2)($4) + sdc1 $f3, (4 * 36 + 8 * 3)($4) + sdc1 $f4, (4 * 36 + 8 * 4)($4) + sdc1 $f5, (4 * 36 + 8 * 5)($4) + sdc1 $f6, (4 * 36 + 8 * 6)($4) + sdc1 $f7, (4 * 36 + 8 * 7)($4) + sdc1 $f8, (4 * 36 + 8 * 8)($4) + sdc1 $f9, (4 * 36 + 8 * 9)($4) + sdc1 $f10, (4 * 36 + 8 * 10)($4) + sdc1 $f11, (4 * 36 + 8 * 11)($4) + sdc1 $f12, (4 * 36 + 8 * 12)($4) + sdc1 $f13, (4 * 36 + 8 * 13)($4) + sdc1 $f14, (4 * 36 + 8 * 14)($4) + sdc1 $f15, (4 * 36 + 8 * 15)($4) + sdc1 $f16, (4 * 36 + 8 * 16)($4) + sdc1 $f17, (4 * 36 + 8 * 17)($4) + sdc1 $f18, (4 * 36 + 8 * 18)($4) + sdc1 $f19, (4 * 36 + 8 * 19)($4) + sdc1 $f20, (4 * 36 + 8 * 20)($4) + sdc1 $f21, (4 * 36 + 8 * 21)($4) + sdc1 $f22, (4 * 36 + 8 * 22)($4) + sdc1 $f23, (4 * 36 + 8 * 23)($4) + sdc1 $f24, (4 * 36 + 8 * 24)($4) + sdc1 $f25, (4 * 36 + 8 * 25)($4) + sdc1 $f26, (4 * 36 + 8 * 26)($4) + sdc1 $f27, (4 * 36 + 8 * 27)($4) + sdc1 $f28, (4 * 36 + 8 * 28)($4) + sdc1 $f29, (4 * 36 + 8 * 29)($4) + sdc1 $f30, (4 * 36 + 8 * 30)($4) + sdc1 $f31, (4 * 36 + 8 * 31)($4) +#endif +#endif + jr $31 + # return UNW_ESUCCESS + or $2, $0, $0 + .set pop + +#elif defined(__mips64) + +# +# extern int unw_getcontext(unw_context_t* thread_state) +# +# On entry: +# thread_state pointer is in a0 ($4) +# +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + .set push + .set noat + .set noreorder + .set nomacro + sd $1, (8 * 1)($4) + sd $2, (8 * 2)($4) + sd $3, (8 * 3)($4) + sd $4, (8 * 4)($4) + sd $5, (8 * 5)($4) + sd $6, (8 * 6)($4) + sd $7, (8 * 7)($4) + sd $8, (8 * 8)($4) + sd $9, (8 * 9)($4) + sd $10, (8 * 10)($4) + sd $11, (8 * 11)($4) + sd $12, (8 * 12)($4) + sd $13, (8 * 13)($4) + sd $14, (8 * 14)($4) + sd $15, (8 * 15)($4) + sd $16, (8 * 16)($4) + sd $17, (8 * 17)($4) + sd $18, (8 * 18)($4) + sd $19, (8 * 19)($4) + sd $20, (8 * 20)($4) + sd $21, (8 * 21)($4) + sd $22, (8 * 22)($4) + sd $23, (8 * 23)($4) + sd $24, (8 * 24)($4) + sd $25, (8 * 25)($4) + sd $26, (8 * 26)($4) + sd $27, (8 * 27)($4) + sd $28, (8 * 28)($4) + sd $29, (8 * 29)($4) + sd $30, (8 * 30)($4) + sd $31, (8 * 31)($4) + # Store return address to pc + sd $31, (8 * 32)($4) + # hi and lo + mfhi $8 + sd $8, (8 * 33)($4) + mflo $8 + sd $8, (8 * 34)($4) +#ifdef __mips_hard_float + sdc1 $f0, (8 * 35)($4) + sdc1 $f1, (8 * 36)($4) + sdc1 $f2, (8 * 37)($4) + sdc1 $f3, (8 * 38)($4) + sdc1 $f4, (8 * 39)($4) + sdc1 $f5, (8 * 40)($4) + sdc1 $f6, (8 * 41)($4) + sdc1 $f7, (8 * 42)($4) + sdc1 $f8, (8 * 43)($4) + sdc1 $f9, (8 * 44)($4) + sdc1 $f10, (8 * 45)($4) + sdc1 $f11, (8 * 46)($4) + sdc1 $f12, (8 * 47)($4) + sdc1 $f13, (8 * 48)($4) + sdc1 $f14, (8 * 49)($4) + sdc1 $f15, (8 * 50)($4) + sdc1 $f16, (8 * 51)($4) + sdc1 $f17, (8 * 52)($4) + sdc1 $f18, (8 * 53)($4) + sdc1 $f19, (8 * 54)($4) + sdc1 $f20, (8 * 55)($4) + sdc1 $f21, (8 * 56)($4) + sdc1 $f22, (8 * 57)($4) + sdc1 $f23, (8 * 58)($4) + sdc1 $f24, (8 * 59)($4) + sdc1 $f25, (8 * 60)($4) + sdc1 $f26, (8 * 61)($4) + sdc1 $f27, (8 * 62)($4) + sdc1 $f28, (8 * 63)($4) + sdc1 $f29, (8 * 64)($4) + sdc1 $f30, (8 * 65)($4) + sdc1 $f31, (8 * 66)($4) +#endif + jr $31 + # return UNW_ESUCCESS + or $2, $0, $0 + .set pop + +# elif defined(__mips__) + +# +# extern int unw_getcontext(unw_context_t* thread_state) +# +# Just trap for the time being. +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + teq $0, $0 + +#elif defined(__powerpc64__) + +// +// extern int unw_getcontext(unw_context_t* thread_state) +// +// On entry: +// thread_state pointer is in r3 +// +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + +// store register (GPR) +#define PPC64_STR(n) \ + std %r##n, (8 * (n + 2))(%r3) + + // save GPRs + PPC64_STR(0) + mflr %r0 + std %r0, PPC64_OFFS_SRR0(%r3) // store lr as ssr0 + PPC64_STR(1) + PPC64_STR(2) + PPC64_STR(3) + PPC64_STR(4) + PPC64_STR(5) + PPC64_STR(6) + PPC64_STR(7) + PPC64_STR(8) + PPC64_STR(9) + PPC64_STR(10) + PPC64_STR(11) + PPC64_STR(12) + PPC64_STR(13) + PPC64_STR(14) + PPC64_STR(15) + PPC64_STR(16) + PPC64_STR(17) + PPC64_STR(18) + PPC64_STR(19) + PPC64_STR(20) + PPC64_STR(21) + PPC64_STR(22) + PPC64_STR(23) + PPC64_STR(24) + PPC64_STR(25) + PPC64_STR(26) + PPC64_STR(27) + PPC64_STR(28) + PPC64_STR(29) + PPC64_STR(30) + PPC64_STR(31) + + mfcr %r0 + std %r0, PPC64_OFFS_CR(%r3) + mfxer %r0 + std %r0, PPC64_OFFS_XER(%r3) + mflr %r0 + std %r0, PPC64_OFFS_LR(%r3) + mfctr %r0 + std %r0, PPC64_OFFS_CTR(%r3) + mfvrsave %r0 + std %r0, PPC64_OFFS_VRSAVE(%r3) + +#ifdef PPC64_HAS_VMX + // save VS registers + // (note that this also saves floating point registers and V registers, + // because part of VS is mapped to these registers) + + addi %r4, %r3, PPC64_OFFS_FP + +// store VS register +#define PPC64_STVS(n) \ + stxvd2x %vs##n, 0, %r4 ;\ + addi %r4, %r4, 16 + + PPC64_STVS(0) + PPC64_STVS(1) + PPC64_STVS(2) + PPC64_STVS(3) + PPC64_STVS(4) + PPC64_STVS(5) + PPC64_STVS(6) + PPC64_STVS(7) + PPC64_STVS(8) + PPC64_STVS(9) + PPC64_STVS(10) + PPC64_STVS(11) + PPC64_STVS(12) + PPC64_STVS(13) + PPC64_STVS(14) + PPC64_STVS(15) + PPC64_STVS(16) + PPC64_STVS(17) + PPC64_STVS(18) + PPC64_STVS(19) + PPC64_STVS(20) + PPC64_STVS(21) + PPC64_STVS(22) + PPC64_STVS(23) + PPC64_STVS(24) + PPC64_STVS(25) + PPC64_STVS(26) + PPC64_STVS(27) + PPC64_STVS(28) + PPC64_STVS(29) + PPC64_STVS(30) + PPC64_STVS(31) + PPC64_STVS(32) + PPC64_STVS(33) + PPC64_STVS(34) + PPC64_STVS(35) + PPC64_STVS(36) + PPC64_STVS(37) + PPC64_STVS(38) + PPC64_STVS(39) + PPC64_STVS(40) + PPC64_STVS(41) + PPC64_STVS(42) + PPC64_STVS(43) + PPC64_STVS(44) + PPC64_STVS(45) + PPC64_STVS(46) + PPC64_STVS(47) + PPC64_STVS(48) + PPC64_STVS(49) + PPC64_STVS(50) + PPC64_STVS(51) + PPC64_STVS(52) + PPC64_STVS(53) + PPC64_STVS(54) + PPC64_STVS(55) + PPC64_STVS(56) + PPC64_STVS(57) + PPC64_STVS(58) + PPC64_STVS(59) + PPC64_STVS(60) + PPC64_STVS(61) + PPC64_STVS(62) + PPC64_STVS(63) + +#else + +// store FP register +#define PPC64_STF(n) \ + stfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3) + + // save float registers + PPC64_STF(0) + PPC64_STF(1) + PPC64_STF(2) + PPC64_STF(3) + PPC64_STF(4) + PPC64_STF(5) + PPC64_STF(6) + PPC64_STF(7) + PPC64_STF(8) + PPC64_STF(9) + PPC64_STF(10) + PPC64_STF(11) + PPC64_STF(12) + PPC64_STF(13) + PPC64_STF(14) + PPC64_STF(15) + PPC64_STF(16) + PPC64_STF(17) + PPC64_STF(18) + PPC64_STF(19) + PPC64_STF(20) + PPC64_STF(21) + PPC64_STF(22) + PPC64_STF(23) + PPC64_STF(24) + PPC64_STF(25) + PPC64_STF(26) + PPC64_STF(27) + PPC64_STF(28) + PPC64_STF(29) + PPC64_STF(30) + PPC64_STF(31) + + // save vector registers + + // Use 16-bytes below the stack pointer as an + // aligned buffer to save each vector register. + // Note that the stack pointer is always 16-byte aligned. + subi %r4, %r1, 16 + +#define PPC64_STV_UNALIGNED(n) \ + stvx %v##n, 0, %r4 ;\ + ld %r5, 0(%r4) ;\ + std %r5, (PPC64_OFFS_V + n * 16)(%r3) ;\ + ld %r5, 8(%r4) ;\ + std %r5, (PPC64_OFFS_V + n * 16 + 8)(%r3) + + PPC64_STV_UNALIGNED(0) + PPC64_STV_UNALIGNED(1) + PPC64_STV_UNALIGNED(2) + PPC64_STV_UNALIGNED(3) + PPC64_STV_UNALIGNED(4) + PPC64_STV_UNALIGNED(5) + PPC64_STV_UNALIGNED(6) + PPC64_STV_UNALIGNED(7) + PPC64_STV_UNALIGNED(8) + PPC64_STV_UNALIGNED(9) + PPC64_STV_UNALIGNED(10) + PPC64_STV_UNALIGNED(11) + PPC64_STV_UNALIGNED(12) + PPC64_STV_UNALIGNED(13) + PPC64_STV_UNALIGNED(14) + PPC64_STV_UNALIGNED(15) + PPC64_STV_UNALIGNED(16) + PPC64_STV_UNALIGNED(17) + PPC64_STV_UNALIGNED(18) + PPC64_STV_UNALIGNED(19) + PPC64_STV_UNALIGNED(20) + PPC64_STV_UNALIGNED(21) + PPC64_STV_UNALIGNED(22) + PPC64_STV_UNALIGNED(23) + PPC64_STV_UNALIGNED(24) + PPC64_STV_UNALIGNED(25) + PPC64_STV_UNALIGNED(26) + PPC64_STV_UNALIGNED(27) + PPC64_STV_UNALIGNED(28) + PPC64_STV_UNALIGNED(29) + PPC64_STV_UNALIGNED(30) + PPC64_STV_UNALIGNED(31) + +#endif + + li %r3, 0 // return UNW_ESUCCESS + blr + + +#elif defined(__ppc__) + +; +; extern int unw_getcontext(unw_context_t* thread_state) +; +; On entry: +; thread_state pointer is in r3 +; +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + stw r0, 8(r3) + mflr r0 + stw r0, 0(r3) ; store lr as ssr0 + stw r1, 12(r3) + stw r2, 16(r3) + stw r3, 20(r3) + stw r4, 24(r3) + stw r5, 28(r3) + stw r6, 32(r3) + stw r7, 36(r3) + stw r8, 40(r3) + stw r9, 44(r3) + stw r10, 48(r3) + stw r11, 52(r3) + stw r12, 56(r3) + stw r13, 60(r3) + stw r14, 64(r3) + stw r15, 68(r3) + stw r16, 72(r3) + stw r17, 76(r3) + stw r18, 80(r3) + stw r19, 84(r3) + stw r20, 88(r3) + stw r21, 92(r3) + stw r22, 96(r3) + stw r23,100(r3) + stw r24,104(r3) + stw r25,108(r3) + stw r26,112(r3) + stw r27,116(r3) + stw r28,120(r3) + stw r29,124(r3) + stw r30,128(r3) + stw r31,132(r3) + + ; save VRSave register + mfspr r0,256 + stw r0,156(r3) + ; save CR registers + mfcr r0 + stw r0,136(r3) + ; save CTR register + mfctr r0 + stw r0,148(r3) + + ; save float registers + stfd f0, 160(r3) + stfd f1, 168(r3) + stfd f2, 176(r3) + stfd f3, 184(r3) + stfd f4, 192(r3) + stfd f5, 200(r3) + stfd f6, 208(r3) + stfd f7, 216(r3) + stfd f8, 224(r3) + stfd f9, 232(r3) + stfd f10,240(r3) + stfd f11,248(r3) + stfd f12,256(r3) + stfd f13,264(r3) + stfd f14,272(r3) + stfd f15,280(r3) + stfd f16,288(r3) + stfd f17,296(r3) + stfd f18,304(r3) + stfd f19,312(r3) + stfd f20,320(r3) + stfd f21,328(r3) + stfd f22,336(r3) + stfd f23,344(r3) + stfd f24,352(r3) + stfd f25,360(r3) + stfd f26,368(r3) + stfd f27,376(r3) + stfd f28,384(r3) + stfd f29,392(r3) + stfd f30,400(r3) + stfd f31,408(r3) + + + ; save vector registers + + subi r4,r1,16 + rlwinm r4,r4,0,0,27 ; mask low 4-bits + ; r4 is now a 16-byte aligned pointer into the red zone + +#define SAVE_VECTOR_UNALIGNED(_vec, _offset) \ + stvx _vec,0,r4 @\ + lwz r5, 0(r4) @\ + stw r5, _offset(r3) @\ + lwz r5, 4(r4) @\ + stw r5, _offset+4(r3) @\ + lwz r5, 8(r4) @\ + stw r5, _offset+8(r3) @\ + lwz r5, 12(r4) @\ + stw r5, _offset+12(r3) + + SAVE_VECTOR_UNALIGNED( v0, 424+0x000) + SAVE_VECTOR_UNALIGNED( v1, 424+0x010) + SAVE_VECTOR_UNALIGNED( v2, 424+0x020) + SAVE_VECTOR_UNALIGNED( v3, 424+0x030) + SAVE_VECTOR_UNALIGNED( v4, 424+0x040) + SAVE_VECTOR_UNALIGNED( v5, 424+0x050) + SAVE_VECTOR_UNALIGNED( v6, 424+0x060) + SAVE_VECTOR_UNALIGNED( v7, 424+0x070) + SAVE_VECTOR_UNALIGNED( v8, 424+0x080) + SAVE_VECTOR_UNALIGNED( v9, 424+0x090) + SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0) + SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0) + SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0) + SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0) + SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0) + SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0) + SAVE_VECTOR_UNALIGNED(v16, 424+0x100) + SAVE_VECTOR_UNALIGNED(v17, 424+0x110) + SAVE_VECTOR_UNALIGNED(v18, 424+0x120) + SAVE_VECTOR_UNALIGNED(v19, 424+0x130) + SAVE_VECTOR_UNALIGNED(v20, 424+0x140) + SAVE_VECTOR_UNALIGNED(v21, 424+0x150) + SAVE_VECTOR_UNALIGNED(v22, 424+0x160) + SAVE_VECTOR_UNALIGNED(v23, 424+0x170) + SAVE_VECTOR_UNALIGNED(v24, 424+0x180) + SAVE_VECTOR_UNALIGNED(v25, 424+0x190) + SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0) + SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0) + SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0) + SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0) + SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0) + SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0) + + li r3, 0 ; return UNW_ESUCCESS + blr + + +#elif defined(__arm64__) || defined(__aarch64__) + +// +// extern int unw_getcontext(unw_context_t* thread_state) +// +// On entry: +// thread_state pointer is in x0 +// + .p2align 2 +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + stp x0, x1, [x0, #0x000] + stp x2, x3, [x0, #0x010] + stp x4, x5, [x0, #0x020] + stp x6, x7, [x0, #0x030] + stp x8, x9, [x0, #0x040] + stp x10,x11, [x0, #0x050] + stp x12,x13, [x0, #0x060] + stp x14,x15, [x0, #0x070] + stp x16,x17, [x0, #0x080] + stp x18,x19, [x0, #0x090] + stp x20,x21, [x0, #0x0A0] + stp x22,x23, [x0, #0x0B0] + stp x24,x25, [x0, #0x0C0] + stp x26,x27, [x0, #0x0D0] + stp x28,x29, [x0, #0x0E0] + str x30, [x0, #0x0F0] + mov x1,sp + str x1, [x0, #0x0F8] + str x30, [x0, #0x100] // store return address as pc + // skip cpsr + stp d0, d1, [x0, #0x110] + stp d2, d3, [x0, #0x120] + stp d4, d5, [x0, #0x130] + stp d6, d7, [x0, #0x140] + stp d8, d9, [x0, #0x150] + stp d10,d11, [x0, #0x160] + stp d12,d13, [x0, #0x170] + stp d14,d15, [x0, #0x180] + stp d16,d17, [x0, #0x190] + stp d18,d19, [x0, #0x1A0] + stp d20,d21, [x0, #0x1B0] + stp d22,d23, [x0, #0x1C0] + stp d24,d25, [x0, #0x1D0] + stp d26,d27, [x0, #0x1E0] + stp d28,d29, [x0, #0x1F0] + str d30, [x0, #0x200] + str d31, [x0, #0x208] + mov x0, #0 // return UNW_ESUCCESS + ret + +#elif defined(__arm__) && !defined(__APPLE__) + +#if !defined(__ARM_ARCH_ISA_ARM) + .thumb +#endif + +@ +@ extern int unw_getcontext(unw_context_t* thread_state) +@ +@ On entry: +@ thread_state pointer is in r0 +@ +@ Per EHABI #4.7 this only saves the core integer registers. +@ EHABI #7.4.5 notes that in general all VRS registers should be restored +@ however this is very hard to do for VFP registers because it is unknown +@ to the library how many registers are implemented by the architecture. +@ Instead, VFP registers are demand saved by logic external to unw_getcontext. +@ + .p2align 2 +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) +#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1 + stm r0!, {r0-r7} + mov r1, r8 + mov r2, r9 + mov r3, r10 + stm r0!, {r1-r3} + mov r1, r11 + mov r2, sp + mov r3, lr + str r1, [r0, #0] @ r11 + @ r12 does not need storing, it it the intra-procedure-call scratch register + str r2, [r0, #8] @ sp + str r3, [r0, #12] @ lr + str r3, [r0, #16] @ store return address as pc + @ T1 does not have a non-cpsr-clobbering register-zeroing instruction. + @ It is safe to use here though because we are about to return, and cpsr is + @ not expected to be preserved. + movs r0, #0 @ return UNW_ESUCCESS +#else + @ 32bit thumb-2 restrictions for stm: + @ . the sp (r13) cannot be in the list + @ . the pc (r15) cannot be in the list in an STM instruction + stm r0, {r0-r12} + str sp, [r0, #52] + str lr, [r0, #56] + str lr, [r0, #60] @ store return address as pc + mov r0, #0 @ return UNW_ESUCCESS +#endif + JMP(lr) + +@ +@ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values) +@ +@ On entry: +@ values pointer is in r0 +@ + .p2align 2 +#if defined(__ELF__) + .fpu vfpv3-d16 +#endif +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy) + vstmia r0, {d0-d15} + JMP(lr) + +@ +@ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values) +@ +@ On entry: +@ values pointer is in r0 +@ + .p2align 2 +#if defined(__ELF__) + .fpu vfpv3-d16 +#endif +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy) + vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia + JMP(lr) + +@ +@ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values) +@ +@ On entry: +@ values pointer is in r0 +@ + .p2align 2 +#if defined(__ELF__) + .fpu vfpv3 +#endif +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy) + @ VFP and iwMMX instructions are only available when compiling with the flags + @ that enable them. We do not want to do that in the library (because we do not + @ want the compiler to generate instructions that access those) but this is + @ only accessed if the personality routine needs these registers. Use of + @ these registers implies they are, actually, available on the target, so + @ it's ok to execute. + @ So, generate the instructions using the corresponding coprocessor mnemonic. + vstmia r0, {d16-d31} + JMP(lr) + +#if defined(_LIBUNWIND_ARM_WMMX) + +@ +@ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values) +@ +@ On entry: +@ values pointer is in r0 +@ + .p2align 2 +#if defined(__ELF__) + .arch armv5te +#endif +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy) + stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8 + stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8 + stcl p1, cr2, [r0], #8 @ wstrd wR2, [r0], #8 + stcl p1, cr3, [r0], #8 @ wstrd wR3, [r0], #8 + stcl p1, cr4, [r0], #8 @ wstrd wR4, [r0], #8 + stcl p1, cr5, [r0], #8 @ wstrd wR5, [r0], #8 + stcl p1, cr6, [r0], #8 @ wstrd wR6, [r0], #8 + stcl p1, cr7, [r0], #8 @ wstrd wR7, [r0], #8 + stcl p1, cr8, [r0], #8 @ wstrd wR8, [r0], #8 + stcl p1, cr9, [r0], #8 @ wstrd wR9, [r0], #8 + stcl p1, cr10, [r0], #8 @ wstrd wR10, [r0], #8 + stcl p1, cr11, [r0], #8 @ wstrd wR11, [r0], #8 + stcl p1, cr12, [r0], #8 @ wstrd wR12, [r0], #8 + stcl p1, cr13, [r0], #8 @ wstrd wR13, [r0], #8 + stcl p1, cr14, [r0], #8 @ wstrd wR14, [r0], #8 + stcl p1, cr15, [r0], #8 @ wstrd wR15, [r0], #8 + JMP(lr) + +@ +@ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values) +@ +@ On entry: +@ values pointer is in r0 +@ + .p2align 2 +#if defined(__ELF__) + .arch armv5te +#endif +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj) + stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4 + stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4 + stc2 p1, cr10, [r0], #4 @ wstrw wCGR2, [r0], #4 + stc2 p1, cr11, [r0], #4 @ wstrw wCGR3, [r0], #4 + JMP(lr) + +#endif + +#elif defined(__or1k__) + +# +# extern int unw_getcontext(unw_context_t* thread_state) +# +# On entry: +# thread_state pointer is in r3 +# +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + l.sw 0(r3), r0 + l.sw 4(r3), r1 + l.sw 8(r3), r2 + l.sw 12(r3), r3 + l.sw 16(r3), r4 + l.sw 20(r3), r5 + l.sw 24(r3), r6 + l.sw 28(r3), r7 + l.sw 32(r3), r8 + l.sw 36(r3), r9 + l.sw 40(r3), r10 + l.sw 44(r3), r11 + l.sw 48(r3), r12 + l.sw 52(r3), r13 + l.sw 56(r3), r14 + l.sw 60(r3), r15 + l.sw 64(r3), r16 + l.sw 68(r3), r17 + l.sw 72(r3), r18 + l.sw 76(r3), r19 + l.sw 80(r3), r20 + l.sw 84(r3), r21 + l.sw 88(r3), r22 + l.sw 92(r3), r23 + l.sw 96(r3), r24 + l.sw 100(r3), r25 + l.sw 104(r3), r26 + l.sw 108(r3), r27 + l.sw 112(r3), r28 + l.sw 116(r3), r29 + l.sw 120(r3), r30 + l.sw 124(r3), r31 + # store ra to pc + l.sw 128(r3), r9 + # zero epcr + l.sw 132(r3), r0 + +#elif defined(__riscv) + +# +# extern int unw_getcontext(unw_context_t* thread_state) +# +# On entry: +# thread_state pointer is in a0 +# +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + // x0 is zero + sd x1, (8 * 1)(a0) + sd x2, (8 * 2)(a0) + sd x3, (8 * 3)(a0) + sd x4, (8 * 4)(a0) + sd x5, (8 * 5)(a0) + sd x6, (8 * 6)(a0) + sd x7, (8 * 7)(a0) + sd x8, (8 * 8)(a0) + sd x9, (8 * 9)(a0) + sd x10, (8 * 10)(a0) + sd x11, (8 * 11)(a0) + sd x12, (8 * 12)(a0) + sd x13, (8 * 13)(a0) + sd x14, (8 * 14)(a0) + sd x15, (8 * 15)(a0) + sd x16, (8 * 16)(a0) + sd x17, (8 * 17)(a0) + sd x18, (8 * 18)(a0) + sd x19, (8 * 19)(a0) + sd x20, (8 * 20)(a0) + sd x21, (8 * 21)(a0) + sd x22, (8 * 22)(a0) + sd x23, (8 * 23)(a0) + sd x24, (8 * 24)(a0) + sd x25, (8 * 25)(a0) + sd x26, (8 * 26)(a0) + sd x27, (8 * 27)(a0) + sd x28, (8 * 28)(a0) + sd x29, (8 * 29)(a0) + sd x30, (8 * 30)(a0) + sd x31, (8 * 31)(a0) + +#ifdef __riscv_float_abi_double + fsd f0, (8 * 32 + 8 * 0)(a0) + fsd f1, (8 * 32 + 8 * 1)(a0) + fsd f2, (8 * 32 + 8 * 2)(a0) + fsd f3, (8 * 32 + 8 * 3)(a0) + fsd f4, (8 * 32 + 8 * 4)(a0) + fsd f5, (8 * 32 + 8 * 5)(a0) + fsd f6, (8 * 32 + 8 * 6)(a0) + fsd f7, (8 * 32 + 8 * 7)(a0) + fsd f8, (8 * 32 + 8 * 8)(a0) + fsd f9, (8 * 32 + 8 * 9)(a0) + fsd f10, (8 * 32 + 8 * 10)(a0) + fsd f11, (8 * 32 + 8 * 11)(a0) + fsd f12, (8 * 32 + 8 * 12)(a0) + fsd f13, (8 * 32 + 8 * 13)(a0) + fsd f14, (8 * 32 + 8 * 14)(a0) + fsd f15, (8 * 32 + 8 * 15)(a0) + fsd f16, (8 * 32 + 8 * 16)(a0) + fsd f17, (8 * 32 + 8 * 17)(a0) + fsd f18, (8 * 32 + 8 * 18)(a0) + fsd f19, (8 * 32 + 8 * 19)(a0) + fsd f20, (8 * 32 + 8 * 20)(a0) + fsd f21, (8 * 32 + 8 * 21)(a0) + fsd f22, (8 * 32 + 8 * 22)(a0) + fsd f23, (8 * 32 + 8 * 23)(a0) + fsd f24, (8 * 32 + 8 * 24)(a0) + fsd f25, (8 * 32 + 8 * 25)(a0) + fsd f26, (8 * 32 + 8 * 26)(a0) + fsd f27, (8 * 32 + 8 * 27)(a0) + fsd f28, (8 * 32 + 8 * 28)(a0) + fsd f29, (8 * 32 + 8 * 29)(a0) + fsd f30, (8 * 32 + 8 * 30)(a0) + fsd f31, (8 * 32 + 8 * 31)(a0) +#endif + + li a0, 0 // return UNW_ESUCCESS + ret // jump to ra + +#elif defined(__sparc__) + +# +# extern int unw_getcontext(unw_context_t* thread_state) +# +# On entry: +# thread_state pointer is in o0 +# +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + ta 3 + add %o7, 8, %o7 + std %g0, [%o0 + 0] + std %g2, [%o0 + 8] + std %g4, [%o0 + 16] + std %g6, [%o0 + 24] + std %o0, [%o0 + 32] + std %o2, [%o0 + 40] + std %o4, [%o0 + 48] + std %o6, [%o0 + 56] + std %l0, [%o0 + 64] + std %l2, [%o0 + 72] + std %l4, [%o0 + 80] + std %l6, [%o0 + 88] + std %i0, [%o0 + 96] + std %i2, [%o0 + 104] + std %i4, [%o0 + 112] + std %i6, [%o0 + 120] + jmp %o7 + clr %o0 // return UNW_ESUCCESS +#endif +#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ + +NO_EXEC_STACK_DIRECTIVE Property changes on: head/contrib/libunwind/src/UnwindRegistersSave.S ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/Unwind_AppleExtras.cpp =================================================================== --- head/contrib/libunwind/src/Unwind_AppleExtras.cpp (nonexistent) +++ head/contrib/libunwind/src/Unwind_AppleExtras.cpp (revision 345068) @@ -0,0 +1,184 @@ +//===--------------------- Unwind_AppleExtras.cpp -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +//===----------------------------------------------------------------------===// + +#include "config.h" +#include "AddressSpace.hpp" +#include "DwarfParser.hpp" + + +// private keymgr stuff +#define KEYMGR_GCC3_DW2_OBJ_LIST 302 +extern "C" { + extern void _keymgr_set_and_unlock_processwide_ptr(int key, void *ptr); + extern void *_keymgr_get_and_lock_processwide_ptr(int key); +} + +// undocumented libgcc "struct object" +struct libgcc_object { + void *start; + void *unused1; + void *unused2; + void *fde; + unsigned long encoding; + void *fde_end; + libgcc_object *next; +}; + +// undocumented libgcc "struct km_object_info" referenced by +// KEYMGR_GCC3_DW2_OBJ_LIST +struct libgcc_object_info { + libgcc_object *seen_objects; + libgcc_object *unseen_objects; + unsigned spare[2]; +}; + + +// static linker symbols to prevent wrong two level namespace for _Unwind symbols +#if defined(__arm__) + #define NOT_HERE_BEFORE_5_0(sym) \ + extern const char sym##_tmp30 __asm("$ld$hide$os3.0$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp30 = 0; \ + extern const char sym##_tmp31 __asm("$ld$hide$os3.1$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp31 = 0; \ + extern const char sym##_tmp32 __asm("$ld$hide$os3.2$_" #sym );\ + __attribute__((visibility("default"))) const char sym##_tmp32 = 0; \ + extern const char sym##_tmp40 __asm("$ld$hide$os4.0$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp40 = 0; \ + extern const char sym##_tmp41 __asm("$ld$hide$os4.1$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp41 = 0; \ + extern const char sym##_tmp42 __asm("$ld$hide$os4.2$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp42 = 0; \ + extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp43 = 0; +#elif defined(__arm64__) + #define NOT_HERE_BEFORE_10_6(sym) + #define NEVER_HERE(sym) +#else + #define NOT_HERE_BEFORE_10_6(sym) \ + extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \ + extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp5 = 0; + #define NEVER_HERE(sym) \ + extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \ + extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \ + extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp6 = 0; +#endif + + +#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) + +// +// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in +// earlier versions +// +NOT_HERE_BEFORE_10_6(_Unwind_DeleteException) +NOT_HERE_BEFORE_10_6(_Unwind_Find_FDE) +NOT_HERE_BEFORE_10_6(_Unwind_ForcedUnwind) +NOT_HERE_BEFORE_10_6(_Unwind_GetGR) +NOT_HERE_BEFORE_10_6(_Unwind_GetIP) +NOT_HERE_BEFORE_10_6(_Unwind_GetLanguageSpecificData) +NOT_HERE_BEFORE_10_6(_Unwind_GetRegionStart) +NOT_HERE_BEFORE_10_6(_Unwind_RaiseException) +NOT_HERE_BEFORE_10_6(_Unwind_Resume) +NOT_HERE_BEFORE_10_6(_Unwind_SetGR) +NOT_HERE_BEFORE_10_6(_Unwind_SetIP) +NOT_HERE_BEFORE_10_6(_Unwind_Backtrace) +NOT_HERE_BEFORE_10_6(_Unwind_FindEnclosingFunction) +NOT_HERE_BEFORE_10_6(_Unwind_GetCFA) +NOT_HERE_BEFORE_10_6(_Unwind_GetDataRelBase) +NOT_HERE_BEFORE_10_6(_Unwind_GetTextRelBase) +NOT_HERE_BEFORE_10_6(_Unwind_Resume_or_Rethrow) +NOT_HERE_BEFORE_10_6(_Unwind_GetIPInfo) +NOT_HERE_BEFORE_10_6(__register_frame) +NOT_HERE_BEFORE_10_6(__deregister_frame) + +// +// symbols in libSystem.dylib for compatibility, but we don't want any new code +// using them +// +NEVER_HERE(__register_frame_info_bases) +NEVER_HERE(__register_frame_info) +NEVER_HERE(__register_frame_info_table_bases) +NEVER_HERE(__register_frame_info_table) +NEVER_HERE(__register_frame_table) +NEVER_HERE(__deregister_frame_info) +NEVER_HERE(__deregister_frame_info_bases) + +#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) + + + + +#if defined(_LIBUNWIND_BUILD_SJLJ_APIS) +// +// symbols in libSystem.dylib in iOS 5.0 and later, but are in libgcc_s.dylib in +// earlier versions +// +NOT_HERE_BEFORE_5_0(_Unwind_GetLanguageSpecificData) +NOT_HERE_BEFORE_5_0(_Unwind_GetRegionStart) +NOT_HERE_BEFORE_5_0(_Unwind_GetIP) +NOT_HERE_BEFORE_5_0(_Unwind_SetGR) +NOT_HERE_BEFORE_5_0(_Unwind_SetIP) +NOT_HERE_BEFORE_5_0(_Unwind_DeleteException) +NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Register) +NOT_HERE_BEFORE_5_0(_Unwind_GetGR) +NOT_HERE_BEFORE_5_0(_Unwind_GetIPInfo) +NOT_HERE_BEFORE_5_0(_Unwind_GetCFA) +NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume) +NOT_HERE_BEFORE_5_0(_Unwind_SjLj_RaiseException) +NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow) +NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister) + +#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS) + + +namespace libunwind { + +_LIBUNWIND_HIDDEN +bool checkKeyMgrRegisteredFDEs(uintptr_t pc, void *&fde) { +#if __MAC_OS_X_VERSION_MIN_REQUIRED + // lastly check for old style keymgr registration of dynamically generated + // FDEs acquire exclusive access to libgcc_object_info + libgcc_object_info *head = (libgcc_object_info *) + _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST); + if (head != NULL) { + // look at each FDE in keymgr + for (libgcc_object *ob = head->unseen_objects; ob != NULL; ob = ob->next) { + CFI_Parser::FDE_Info fdeInfo; + CFI_Parser::CIE_Info cieInfo; + const char *msg = CFI_Parser::decodeFDE( + LocalAddressSpace::sThisAddressSpace, + (uintptr_t)ob->fde, &fdeInfo, &cieInfo); + if (msg == NULL) { + // Check if this FDE is for a function that includes the pc + if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) { + fde = (void*)fdeInfo.pcStart; + _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, + head); + return true; + } + } + } + } + // release libgcc_object_info + _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head); +#else + (void)pc; + (void)fde; +#endif + return false; +} + +} + Property changes on: head/contrib/libunwind/src/Unwind_AppleExtras.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/assembly.h =================================================================== --- head/contrib/libunwind/src/assembly.h (nonexistent) +++ head/contrib/libunwind/src/assembly.h (revision 345068) @@ -0,0 +1,124 @@ +/* ===-- assembly.h - libUnwind assembler support macros -------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file defines macros for use in libUnwind assembler source. + * This file is not part of the interface of this library. + * + * ===----------------------------------------------------------------------=== + */ + +#ifndef UNWIND_ASSEMBLY_H +#define UNWIND_ASSEMBLY_H + +#if defined(__powerpc64__) +#define SEPARATOR ; +#define PPC64_OFFS_SRR0 0 +#define PPC64_OFFS_CR 272 +#define PPC64_OFFS_XER 280 +#define PPC64_OFFS_LR 288 +#define PPC64_OFFS_CTR 296 +#define PPC64_OFFS_VRSAVE 304 +#define PPC64_OFFS_FP 312 +#define PPC64_OFFS_V 824 +#ifdef _ARCH_PWR8 +#define PPC64_HAS_VMX +#endif +#elif defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__) +#define SEPARATOR @ +#elif defined(__arm64__) +#define SEPARATOR %% +#else +#define SEPARATOR ; +#endif + +#define GLUE2(a, b) a ## b +#define GLUE(a, b) GLUE2(a, b) +#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name) + +#if defined(__APPLE__) + +#define SYMBOL_IS_FUNC(name) +#define EXPORT_SYMBOL(name) +#define HIDDEN_SYMBOL(name) .private_extern name +#define NO_EXEC_STACK_DIRECTIVE + +#elif defined(__ELF__) + +#if defined(__arm__) +#define SYMBOL_IS_FUNC(name) .type name,%function +#else +#define SYMBOL_IS_FUNC(name) .type name,@function +#endif +#define EXPORT_SYMBOL(name) +#define HIDDEN_SYMBOL(name) .hidden name + +#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \ + defined(__linux__) +#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits +#else +#define NO_EXEC_STACK_DIRECTIVE +#endif + +#elif defined(_WIN32) + +#define SYMBOL_IS_FUNC(name) \ + .def name SEPARATOR \ + .scl 2 SEPARATOR \ + .type 32 SEPARATOR \ + .endef +#define EXPORT_SYMBOL2(name) \ + .section .drectve,"yn" SEPARATOR \ + .ascii "-export:", #name, "\0" SEPARATOR \ + .text +#if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS) +#define EXPORT_SYMBOL(name) +#else +#define EXPORT_SYMBOL(name) EXPORT_SYMBOL2(name) +#endif +#define HIDDEN_SYMBOL(name) + +#define NO_EXEC_STACK_DIRECTIVE + +#elif defined(__sparc__) + +#else + +#error Unsupported target + +#endif + +#define DEFINE_LIBUNWIND_FUNCTION(name) \ + .globl SYMBOL_NAME(name) SEPARATOR \ + EXPORT_SYMBOL(name) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + SYMBOL_NAME(name): + +#define DEFINE_LIBUNWIND_PRIVATE_FUNCTION(name) \ + .globl SYMBOL_NAME(name) SEPARATOR \ + HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + SYMBOL_NAME(name): + +#if defined(__arm__) +#if !defined(__ARM_ARCH) +#define __ARM_ARCH 4 +#endif + +#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5 +#define ARM_HAS_BX +#endif + +#ifdef ARM_HAS_BX +#define JMP(r) bx r +#else +#define JMP(r) mov pc, r +#endif +#endif /* __arm__ */ + +#endif /* UNWIND_ASSEMBLY_H */ Property changes on: head/contrib/libunwind/src/assembly.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/config.h =================================================================== --- head/contrib/libunwind/src/config.h (nonexistent) +++ head/contrib/libunwind/src/config.h (revision 345068) @@ -0,0 +1,184 @@ +//===----------------------------- config.h -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Defines macros used within libunwind project. +// +//===----------------------------------------------------------------------===// + + +#ifndef LIBUNWIND_CONFIG_H +#define LIBUNWIND_CONFIG_H + +#include +#include +#include +#include + +// Define static_assert() unless already defined by compiler. +#ifndef __has_feature + #define __has_feature(__x) 0 +#endif +#if !(__has_feature(cxx_static_assert)) && !defined(static_assert) + #define static_assert(__b, __m) \ + extern int compile_time_assert_failed[ ( __b ) ? 1 : -1 ] \ + __attribute__( ( unused ) ); +#endif + +// Platform specific configuration defines. +#ifdef __APPLE__ + #if defined(FOR_DYLD) + #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND + #else + #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND + #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 + #endif +#elif defined(_WIN32) + #ifdef __SEH__ + #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1 + #else + #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 + #endif +#else + #if defined(__ARM_DWARF_EH__) || !defined(__arm__) + #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 + #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 + #endif +#endif + +#if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS) + #define _LIBUNWIND_EXPORT + #define _LIBUNWIND_HIDDEN +#else + #if !defined(__ELF__) && !defined(__MACH__) + #define _LIBUNWIND_EXPORT __declspec(dllexport) + #define _LIBUNWIND_HIDDEN + #else + #define _LIBUNWIND_EXPORT __attribute__((visibility("default"))) + #define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden"))) + #endif +#endif + +#if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__) +#define _LIBUNWIND_BUILD_SJLJ_APIS +#endif + +#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) +#define _LIBUNWIND_SUPPORT_FRAME_APIS +#endif + +#if defined(__i386__) || defined(__x86_64__) || \ + defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \ + (!defined(__APPLE__) && defined(__arm__)) || \ + (defined(__arm64__) || defined(__aarch64__)) || \ + defined(__mips__) || \ + defined(__riscv) +#if !defined(_LIBUNWIND_BUILD_SJLJ_APIS) +#define _LIBUNWIND_BUILD_ZERO_COST_APIS +#endif +#endif + +#if defined(__powerpc64__) && defined(_ARCH_PWR8) +#define PPC64_HAS_VMX +#endif + +#if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL) +#define _LIBUNWIND_ABORT(msg) \ + do { \ + abort(); \ + } while (0) +#else +#define _LIBUNWIND_ABORT(msg) \ + do { \ + fprintf(stderr, "libunwind: %s %s:%d - %s\n", __func__, __FILE__, \ + __LINE__, msg); \ + fflush(stderr); \ + abort(); \ + } while (0) +#endif + +#if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL) +#define _LIBUNWIND_LOG0(msg) +#define _LIBUNWIND_LOG(msg, ...) +#else +#define _LIBUNWIND_LOG0(msg) \ + fprintf(stderr, "libunwind: " msg "\n") +#define _LIBUNWIND_LOG(msg, ...) \ + fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__) +#endif + +#if defined(NDEBUG) + #define _LIBUNWIND_LOG_IF_FALSE(x) x +#else + #define _LIBUNWIND_LOG_IF_FALSE(x) \ + do { \ + bool _ret = x; \ + if (!_ret) \ + _LIBUNWIND_LOG("" #x " failed in %s", __FUNCTION__); \ + } while (0) +#endif + +// Macros that define away in non-Debug builds +#ifdef NDEBUG + #define _LIBUNWIND_DEBUG_LOG(msg, ...) + #define _LIBUNWIND_TRACE_API(msg, ...) + #define _LIBUNWIND_TRACING_UNWINDING (0) + #define _LIBUNWIND_TRACING_DWARF (0) + #define _LIBUNWIND_TRACE_UNWINDING(msg, ...) + #define _LIBUNWIND_TRACE_DWARF(...) +#else + #ifdef __cplusplus + extern "C" { + #endif + extern bool logAPIs(); + extern bool logUnwinding(); + extern bool logDWARF(); + #ifdef __cplusplus + } + #endif + #define _LIBUNWIND_DEBUG_LOG(msg, ...) _LIBUNWIND_LOG(msg, __VA_ARGS__) + #define _LIBUNWIND_TRACE_API(msg, ...) \ + do { \ + if (logAPIs()) \ + _LIBUNWIND_LOG(msg, __VA_ARGS__); \ + } while (0) + #define _LIBUNWIND_TRACING_UNWINDING logUnwinding() + #define _LIBUNWIND_TRACING_DWARF logDWARF() + #define _LIBUNWIND_TRACE_UNWINDING(msg, ...) \ + do { \ + if (logUnwinding()) \ + _LIBUNWIND_LOG(msg, __VA_ARGS__); \ + } while (0) + #define _LIBUNWIND_TRACE_DWARF(...) \ + do { \ + if (logDWARF()) \ + fprintf(stderr, __VA_ARGS__); \ + } while (0) +#endif + +#ifdef __cplusplus +// Used to fit UnwindCursor and Registers_xxx types against unw_context_t / +// unw_cursor_t sized memory blocks. +#if defined(_LIBUNWIND_IS_NATIVE_ONLY) +# define COMP_OP == +#else +# define COMP_OP <= +#endif +template +struct check_fit { + template + struct blk_count { + static const size_t count = + (sizeof(T) + sizeof(uint64_t) - 1) / sizeof(uint64_t); + }; + static const bool does_fit = + (blk_count<_Type>::count COMP_OP blk_count<_Mem>::count); +}; +#undef COMP_OP +#endif // __cplusplus + +#endif // LIBUNWIND_CONFIG_H Property changes on: head/contrib/libunwind/src/config.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/dwarf2.h =================================================================== --- head/contrib/libunwind/src/dwarf2.h (nonexistent) +++ head/contrib/libunwind/src/dwarf2.h (revision 345068) @@ -0,0 +1,240 @@ +//===------------------------------- dwarf2.h -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +/* + These constants were taken from version 3 of the DWARF standard, + which is Copyright (c) 2005 Free Standards Group, and + Copyright (c) 1992, 1993 UNIX International, Inc. +*/ + +#ifndef __DWARF2__ +#define __DWARF2__ + +// DWARF unwind instructions +enum { + DW_CFA_nop = 0x0, + DW_CFA_set_loc = 0x1, + DW_CFA_advance_loc1 = 0x2, + DW_CFA_advance_loc2 = 0x3, + DW_CFA_advance_loc4 = 0x4, + DW_CFA_offset_extended = 0x5, + DW_CFA_restore_extended = 0x6, + DW_CFA_undefined = 0x7, + DW_CFA_same_value = 0x8, + DW_CFA_register = 0x9, + DW_CFA_remember_state = 0xA, + DW_CFA_restore_state = 0xB, + DW_CFA_def_cfa = 0xC, + DW_CFA_def_cfa_register = 0xD, + DW_CFA_def_cfa_offset = 0xE, + DW_CFA_def_cfa_expression = 0xF, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + DW_CFA_advance_loc = 0x40, // high 2 bits are 0x1, lower 6 bits are delta + DW_CFA_offset = 0x80, // high 2 bits are 0x2, lower 6 bits are register + DW_CFA_restore = 0xC0, // high 2 bits are 0x3, lower 6 bits are register + + // GNU extensions + DW_CFA_GNU_window_save = 0x2D, + DW_CFA_GNU_args_size = 0x2E, + DW_CFA_GNU_negative_offset_extended = 0x2F, + + // AARCH64 extensions + DW_CFA_AARCH64_negate_ra_state = 0x2D +}; + + +// FSF exception handling Pointer-Encoding constants +// Used in CFI augmentation by GCC +enum { + DW_EH_PE_ptr = 0x00, + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + DW_EH_PE_signed = 0x08, + DW_EH_PE_sleb128 = 0x09, + DW_EH_PE_sdata2 = 0x0A, + DW_EH_PE_sdata4 = 0x0B, + DW_EH_PE_sdata8 = 0x0C, + DW_EH_PE_absptr = 0x00, + DW_EH_PE_pcrel = 0x10, + DW_EH_PE_textrel = 0x20, + DW_EH_PE_datarel = 0x30, + DW_EH_PE_funcrel = 0x40, + DW_EH_PE_aligned = 0x50, + DW_EH_PE_indirect = 0x80, + DW_EH_PE_omit = 0xFF +}; + + +// DWARF expressions +enum { + DW_OP_addr = 0x03, // constant address (size target specific) + DW_OP_deref = 0x06, + DW_OP_const1u = 0x08, // 1-byte constant + DW_OP_const1s = 0x09, // 1-byte constant + DW_OP_const2u = 0x0A, // 2-byte constant + DW_OP_const2s = 0x0B, // 2-byte constant + DW_OP_const4u = 0x0C, // 4-byte constant + DW_OP_const4s = 0x0D, // 4-byte constant + DW_OP_const8u = 0x0E, // 8-byte constant + DW_OP_const8s = 0x0F, // 8-byte constant + DW_OP_constu = 0x10, // ULEB128 constant + DW_OP_consts = 0x11, // SLEB128 constant + DW_OP_dup = 0x12, + DW_OP_drop = 0x13, + DW_OP_over = 0x14, + DW_OP_pick = 0x15, // 1-byte stack index + DW_OP_swap = 0x16, + DW_OP_rot = 0x17, + DW_OP_xderef = 0x18, + DW_OP_abs = 0x19, + DW_OP_and = 0x1A, + DW_OP_div = 0x1B, + DW_OP_minus = 0x1C, + DW_OP_mod = 0x1D, + DW_OP_mul = 0x1E, + DW_OP_neg = 0x1F, + DW_OP_not = 0x20, + DW_OP_or = 0x21, + DW_OP_plus = 0x22, + DW_OP_plus_uconst = 0x23, // ULEB128 addend + DW_OP_shl = 0x24, + DW_OP_shr = 0x25, + DW_OP_shra = 0x26, + DW_OP_xor = 0x27, + DW_OP_skip = 0x2F, // signed 2-byte constant + DW_OP_bra = 0x28, // signed 2-byte constant + DW_OP_eq = 0x29, + DW_OP_ge = 0x2A, + DW_OP_gt = 0x2B, + DW_OP_le = 0x2C, + DW_OP_lt = 0x2D, + DW_OP_ne = 0x2E, + DW_OP_lit0 = 0x30, // Literal 0 + DW_OP_lit1 = 0x31, // Literal 1 + DW_OP_lit2 = 0x32, // Literal 2 + DW_OP_lit3 = 0x33, // Literal 3 + DW_OP_lit4 = 0x34, // Literal 4 + DW_OP_lit5 = 0x35, // Literal 5 + DW_OP_lit6 = 0x36, // Literal 6 + DW_OP_lit7 = 0x37, // Literal 7 + DW_OP_lit8 = 0x38, // Literal 8 + DW_OP_lit9 = 0x39, // Literal 9 + DW_OP_lit10 = 0x3A, // Literal 10 + DW_OP_lit11 = 0x3B, // Literal 11 + DW_OP_lit12 = 0x3C, // Literal 12 + DW_OP_lit13 = 0x3D, // Literal 13 + DW_OP_lit14 = 0x3E, // Literal 14 + DW_OP_lit15 = 0x3F, // Literal 15 + DW_OP_lit16 = 0x40, // Literal 16 + DW_OP_lit17 = 0x41, // Literal 17 + DW_OP_lit18 = 0x42, // Literal 18 + DW_OP_lit19 = 0x43, // Literal 19 + DW_OP_lit20 = 0x44, // Literal 20 + DW_OP_lit21 = 0x45, // Literal 21 + DW_OP_lit22 = 0x46, // Literal 22 + DW_OP_lit23 = 0x47, // Literal 23 + DW_OP_lit24 = 0x48, // Literal 24 + DW_OP_lit25 = 0x49, // Literal 25 + DW_OP_lit26 = 0x4A, // Literal 26 + DW_OP_lit27 = 0x4B, // Literal 27 + DW_OP_lit28 = 0x4C, // Literal 28 + DW_OP_lit29 = 0x4D, // Literal 29 + DW_OP_lit30 = 0x4E, // Literal 30 + DW_OP_lit31 = 0x4F, // Literal 31 + DW_OP_reg0 = 0x50, // Contents of reg0 + DW_OP_reg1 = 0x51, // Contents of reg1 + DW_OP_reg2 = 0x52, // Contents of reg2 + DW_OP_reg3 = 0x53, // Contents of reg3 + DW_OP_reg4 = 0x54, // Contents of reg4 + DW_OP_reg5 = 0x55, // Contents of reg5 + DW_OP_reg6 = 0x56, // Contents of reg6 + DW_OP_reg7 = 0x57, // Contents of reg7 + DW_OP_reg8 = 0x58, // Contents of reg8 + DW_OP_reg9 = 0x59, // Contents of reg9 + DW_OP_reg10 = 0x5A, // Contents of reg10 + DW_OP_reg11 = 0x5B, // Contents of reg11 + DW_OP_reg12 = 0x5C, // Contents of reg12 + DW_OP_reg13 = 0x5D, // Contents of reg13 + DW_OP_reg14 = 0x5E, // Contents of reg14 + DW_OP_reg15 = 0x5F, // Contents of reg15 + DW_OP_reg16 = 0x60, // Contents of reg16 + DW_OP_reg17 = 0x61, // Contents of reg17 + DW_OP_reg18 = 0x62, // Contents of reg18 + DW_OP_reg19 = 0x63, // Contents of reg19 + DW_OP_reg20 = 0x64, // Contents of reg20 + DW_OP_reg21 = 0x65, // Contents of reg21 + DW_OP_reg22 = 0x66, // Contents of reg22 + DW_OP_reg23 = 0x67, // Contents of reg23 + DW_OP_reg24 = 0x68, // Contents of reg24 + DW_OP_reg25 = 0x69, // Contents of reg25 + DW_OP_reg26 = 0x6A, // Contents of reg26 + DW_OP_reg27 = 0x6B, // Contents of reg27 + DW_OP_reg28 = 0x6C, // Contents of reg28 + DW_OP_reg29 = 0x6D, // Contents of reg29 + DW_OP_reg30 = 0x6E, // Contents of reg30 + DW_OP_reg31 = 0x6F, // Contents of reg31 + DW_OP_breg0 = 0x70, // base register 0 + SLEB128 offset + DW_OP_breg1 = 0x71, // base register 1 + SLEB128 offset + DW_OP_breg2 = 0x72, // base register 2 + SLEB128 offset + DW_OP_breg3 = 0x73, // base register 3 + SLEB128 offset + DW_OP_breg4 = 0x74, // base register 4 + SLEB128 offset + DW_OP_breg5 = 0x75, // base register 5 + SLEB128 offset + DW_OP_breg6 = 0x76, // base register 6 + SLEB128 offset + DW_OP_breg7 = 0x77, // base register 7 + SLEB128 offset + DW_OP_breg8 = 0x78, // base register 8 + SLEB128 offset + DW_OP_breg9 = 0x79, // base register 9 + SLEB128 offset + DW_OP_breg10 = 0x7A, // base register 10 + SLEB128 offset + DW_OP_breg11 = 0x7B, // base register 11 + SLEB128 offset + DW_OP_breg12 = 0x7C, // base register 12 + SLEB128 offset + DW_OP_breg13 = 0x7D, // base register 13 + SLEB128 offset + DW_OP_breg14 = 0x7E, // base register 14 + SLEB128 offset + DW_OP_breg15 = 0x7F, // base register 15 + SLEB128 offset + DW_OP_breg16 = 0x80, // base register 16 + SLEB128 offset + DW_OP_breg17 = 0x81, // base register 17 + SLEB128 offset + DW_OP_breg18 = 0x82, // base register 18 + SLEB128 offset + DW_OP_breg19 = 0x83, // base register 19 + SLEB128 offset + DW_OP_breg20 = 0x84, // base register 20 + SLEB128 offset + DW_OP_breg21 = 0x85, // base register 21 + SLEB128 offset + DW_OP_breg22 = 0x86, // base register 22 + SLEB128 offset + DW_OP_breg23 = 0x87, // base register 23 + SLEB128 offset + DW_OP_breg24 = 0x88, // base register 24 + SLEB128 offset + DW_OP_breg25 = 0x89, // base register 25 + SLEB128 offset + DW_OP_breg26 = 0x8A, // base register 26 + SLEB128 offset + DW_OP_breg27 = 0x8B, // base register 27 + SLEB128 offset + DW_OP_breg28 = 0x8C, // base register 28 + SLEB128 offset + DW_OP_breg29 = 0x8D, // base register 29 + SLEB128 offset + DW_OP_breg30 = 0x8E, // base register 30 + SLEB128 offset + DW_OP_breg31 = 0x8F, // base register 31 + SLEB128 offset + DW_OP_regx = 0x90, // ULEB128 register + DW_OP_fbreg = 0x91, // SLEB128 offset + DW_OP_bregx = 0x92, // ULEB128 register followed by SLEB128 offset + DW_OP_piece = 0x93, // ULEB128 size of piece addressed + DW_OP_deref_size = 0x94, // 1-byte size of data retrieved + DW_OP_xderef_size = 0x95, // 1-byte size of data retrieved + DW_OP_nop = 0x96, + DW_OP_push_object_addres = 0x97, + DW_OP_call2 = 0x98, // 2-byte offset of DIE + DW_OP_call4 = 0x99, // 4-byte offset of DIE + DW_OP_call_ref = 0x9A, // 4- or 8-byte offset of DIE + DW_OP_lo_user = 0xE0, + DW_OP_APPLE_uninit = 0xF0, + DW_OP_hi_user = 0xFF +}; + + +#endif Property changes on: head/contrib/libunwind/src/dwarf2.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/libunwind.cpp =================================================================== --- head/contrib/libunwind/src/libunwind.cpp (nonexistent) +++ head/contrib/libunwind/src/libunwind.cpp (revision 345068) @@ -0,0 +1,412 @@ +//===--------------------------- libunwind.cpp ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Implements unw_* functions from +// +//===----------------------------------------------------------------------===// + +#include + +#ifndef NDEBUG +#include // getenv +#endif +#include +#include + +#include "libunwind_ext.h" +#include "config.h" + +#include + + +#if !defined(__USING_SJLJ_EXCEPTIONS__) +#include "AddressSpace.hpp" +#include "UnwindCursor.hpp" + +using namespace libunwind; + +/// internal object to represent this processes address space +LocalAddressSpace LocalAddressSpace::sThisAddressSpace; + +_LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space = + (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace; + +/// record the registers and stack position of the caller +extern int unw_getcontext(unw_context_t *); +// note: unw_getcontext() implemented in assembly + +/// Create a cursor of a thread in this process given 'context' recorded by +/// unw_getcontext(). +_LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor, + unw_context_t *context) { + _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)", + static_cast(cursor), + static_cast(context)); +#if defined(__i386__) +# define REGISTER_KIND Registers_x86 +#elif defined(__x86_64__) +# define REGISTER_KIND Registers_x86_64 +#elif defined(__powerpc64__) +# define REGISTER_KIND Registers_ppc64 +#elif defined(__ppc__) +# define REGISTER_KIND Registers_ppc +#elif defined(__aarch64__) +# define REGISTER_KIND Registers_arm64 +#elif defined(__arm__) +# define REGISTER_KIND Registers_arm +#elif defined(__or1k__) +# define REGISTER_KIND Registers_or1k +#elif defined(__riscv) +# define REGISTER_KIND Registers_riscv +#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 +# define REGISTER_KIND Registers_mips_o32 +#elif defined(__mips64) +# define REGISTER_KIND Registers_mips_newabi +#elif defined(__mips__) +# warning The MIPS architecture is not supported with this ABI and environment! +#elif defined(__sparc__) +# define REGISTER_KIND Registers_sparc +#else +# error Architecture not supported +#endif + // Use "placement new" to allocate UnwindCursor in the cursor buffer. + new ((void *)cursor) UnwindCursor( + context, LocalAddressSpace::sThisAddressSpace); +#undef REGISTER_KIND + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + co->setInfoBasedOnIPRegister(); + + return UNW_ESUCCESS; +} + +#ifdef UNW_REMOTE +/// Create a cursor into a thread in another process. +_LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor, + unw_addr_space_t as, + void *arg) { + // special case: unw_init_remote(xx, unw_local_addr_space, xx) + if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace) + return unw_init_local(cursor, NULL); //FIXME + + // use "placement new" to allocate UnwindCursor in the cursor buffer + switch (as->cpuType) { + case CPU_TYPE_I386: + new ((void *)cursor) + UnwindCursor>, + Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg); + break; + case CPU_TYPE_X86_64: + new ((void *)cursor) + UnwindCursor>, + Registers_x86_64>(((unw_addr_space_x86_64 *)as)->oas, arg); + break; + case CPU_TYPE_POWERPC: + new ((void *)cursor) + UnwindCursor>, + Registers_ppc>(((unw_addr_space_ppc *)as)->oas, arg); + break; + default: + return UNW_EUNSPEC; + } + return UNW_ESUCCESS; +} + + +static bool is64bit(task_t task) { + return false; // FIXME +} + +/// Create an address_space object for use in examining another task. +_LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) { +#if __i386__ + if (is64bit(task)) { + unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task); + as->taskPort = task; + as->cpuType = CPU_TYPE_X86_64; + //as->oas + } else { + unw_addr_space_i386 *as = new unw_addr_space_i386(task); + as->taskPort = task; + as->cpuType = CPU_TYPE_I386; + //as->oas + } +#else +// FIXME +#endif +} + + +/// Delete an address_space object. +_LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) { + switch (asp->cpuType) { +#if __i386__ || __x86_64__ + case CPU_TYPE_I386: { + unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp; + delete as; + } + break; + case CPU_TYPE_X86_64: { + unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp; + delete as; + } + break; +#endif + case CPU_TYPE_POWERPC: { + unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp; + delete as; + } + break; + } +} +#endif // UNW_REMOTE + + +/// Get value of specified register at cursor position in stack frame. +_LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum, + unw_word_t *value) { + _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)", + static_cast(cursor), regNum, + static_cast(value)); + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + if (co->validReg(regNum)) { + *value = co->getReg(regNum); + return UNW_ESUCCESS; + } + return UNW_EBADREG; +} + + +/// Set value of specified register at cursor position in stack frame. +_LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, + unw_word_t value) { + _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%" PRIxPTR ")", + static_cast(cursor), regNum, value); + typedef LocalAddressSpace::pint_t pint_t; + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + if (co->validReg(regNum)) { + co->setReg(regNum, (pint_t)value); + // specical case altering IP to re-find info (being called by personality + // function) + if (regNum == UNW_REG_IP) { + unw_proc_info_t info; + // First, get the FDE for the old location and then update it. + co->getInfo(&info); + co->setInfoBasedOnIPRegister(false); + // If the original call expects stack adjustment, perform this now. + // Normal frame unwinding would have included the offset already in the + // CFA computation. + // Note: for PA-RISC and other platforms where the stack grows up, + // this should actually be - info.gp. LLVM doesn't currently support + // any such platforms and Clang doesn't export a macro for them. + if (info.gp) + co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp); + } + return UNW_ESUCCESS; + } + return UNW_EBADREG; +} + + +/// Get value of specified float register at cursor position in stack frame. +_LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, + unw_fpreg_t *value) { + _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)", + static_cast(cursor), regNum, + static_cast(value)); + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + if (co->validFloatReg(regNum)) { + *value = co->getFloatReg(regNum); + return UNW_ESUCCESS; + } + return UNW_EBADREG; +} + + +/// Set value of specified float register at cursor position in stack frame. +_LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, + unw_fpreg_t value) { +#if defined(_LIBUNWIND_ARM_EHABI) + _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)", + static_cast(cursor), regNum, value); +#else + _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)", + static_cast(cursor), regNum, value); +#endif + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + if (co->validFloatReg(regNum)) { + co->setFloatReg(regNum, value); + return UNW_ESUCCESS; + } + return UNW_EBADREG; +} + + +/// Move cursor to next frame. +_LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) { + _LIBUNWIND_TRACE_API("unw_step(cursor=%p)", static_cast(cursor)); + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + return co->step(); +} + + +/// Get unwind info at cursor position in stack frame. +_LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor, + unw_proc_info_t *info) { + _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)", + static_cast(cursor), static_cast(info)); + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + co->getInfo(info); + if (info->end_ip == 0) + return UNW_ENOINFO; + else + return UNW_ESUCCESS; +} + + +/// Resume execution at cursor position (aka longjump). +_LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) { + _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)", static_cast(cursor)); + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + co->jumpto(); + return UNW_EUNSPEC; +} + + +/// Get name of function at cursor position in stack frame. +_LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf, + size_t bufLen, unw_word_t *offset) { + _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)", + static_cast(cursor), static_cast(buf), + static_cast(bufLen)); + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + if (co->getFunctionName(buf, bufLen, offset)) + return UNW_ESUCCESS; + else + return UNW_EUNSPEC; +} + + +/// Checks if a register is a floating-point register. +_LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) { + _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)", + static_cast(cursor), regNum); + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + return co->validFloatReg(regNum); +} + + +/// Checks if a register is a floating-point register. +_LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor, + unw_regnum_t regNum) { + _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)", + static_cast(cursor), regNum); + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + return co->getRegisterName(regNum); +} + + +/// Checks if current frame is signal trampoline. +_LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) { + _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)", + static_cast(cursor)); + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + return co->isSignalFrame(); +} + +#ifdef __arm__ +// Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD +_LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) { + _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)", + static_cast(cursor)); + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + return co->saveVFPAsX(); +} +#endif + + +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) +/// SPI: walks cached DWARF entries +_LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)( + unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { + _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)", + reinterpret_cast(func)); + DwarfFDECache::iterateCacheEntries(func); +} + + +/// IPI: for __register_frame() +void _unw_add_dynamic_fde(unw_word_t fde) { + CFI_Parser::FDE_Info fdeInfo; + CFI_Parser::CIE_Info cieInfo; + const char *message = CFI_Parser::decodeFDE( + LocalAddressSpace::sThisAddressSpace, + (LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo); + if (message == NULL) { + // dynamically registered FDEs don't have a mach_header group they are in. + // Use fde as mh_group + unw_word_t mh_group = fdeInfo.fdeStart; + DwarfFDECache::add((LocalAddressSpace::pint_t)mh_group, + fdeInfo.pcStart, fdeInfo.pcEnd, + fdeInfo.fdeStart); + } else { + _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message); + } +} + +/// IPI: for __deregister_frame() +void _unw_remove_dynamic_fde(unw_word_t fde) { + // fde is own mh_group + DwarfFDECache::removeAllIn((LocalAddressSpace::pint_t)fde); +} +#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) +#endif // !defined(__USING_SJLJ_EXCEPTIONS__) + + + +// Add logging hooks in Debug builds only +#ifndef NDEBUG +#include + +_LIBUNWIND_HIDDEN +bool logAPIs() { + // do manual lock to avoid use of _cxa_guard_acquire or initializers + static bool checked = false; + static bool log = false; + if (!checked) { + log = (getenv("LIBUNWIND_PRINT_APIS") != NULL); + checked = true; + } + return log; +} + +_LIBUNWIND_HIDDEN +bool logUnwinding() { + // do manual lock to avoid use of _cxa_guard_acquire or initializers + static bool checked = false; + static bool log = false; + if (!checked) { + log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL); + checked = true; + } + return log; +} + +_LIBUNWIND_HIDDEN +bool logDWARF() { + // do manual lock to avoid use of _cxa_guard_acquire or initializers + static bool checked = false; + static bool log = false; + if (!checked) { + log = (getenv("LIBUNWIND_PRINT_DWARF") != NULL); + checked = true; + } + return log; +} + +#endif // NDEBUG + Property changes on: head/contrib/libunwind/src/libunwind.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/src/libunwind_ext.h =================================================================== --- head/contrib/libunwind/src/libunwind_ext.h (nonexistent) +++ head/contrib/libunwind/src/libunwind_ext.h (revision 345068) @@ -0,0 +1,47 @@ +//===------------------------ libunwind_ext.h -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Extensions to libunwind API. +// +//===----------------------------------------------------------------------===// + +#ifndef __LIBUNWIND_EXT__ +#define __LIBUNWIND_EXT__ + +#include "config.h" +#include +#include + +#define UNW_STEP_SUCCESS 1 +#define UNW_STEP_END 0 + +#ifdef __cplusplus +extern "C" { +#endif +// SPI +extern void unw_iterate_dwarf_unwind_cache(void (*func)(unw_word_t ip_start, + unw_word_t ip_end, + unw_word_t fde, + unw_word_t mh)); + +// IPI +extern void _unw_add_dynamic_fde(unw_word_t fde); +extern void _unw_remove_dynamic_fde(unw_word_t fde); + +#if defined(_LIBUNWIND_ARM_EHABI) +extern const uint32_t* decode_eht_entry(const uint32_t*, size_t*, size_t*); +extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context, + const uint32_t *data, + size_t offset, size_t len); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // __LIBUNWIND_EXT__ Property changes on: head/contrib/libunwind/src/libunwind_ext.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/LICENSE.TXT =================================================================== --- head/contrib/libunwind/LICENSE.TXT (nonexistent) +++ head/contrib/libunwind/LICENSE.TXT (revision 345068) @@ -0,0 +1,76 @@ +============================================================================== +libunwind License +============================================================================== + +The libunwind library is dual licensed under both the University of Illinois +"BSD-Like" license and the MIT license. As a user of this code you may choose +to use it under either license. As a contributor, you agree to allow your code +to be used under both. + +Full text of the relevant licenses is included below. + +============================================================================== + +University of Illinois/NCSA +Open Source License + +Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT + +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== + +Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. Property changes on: head/contrib/libunwind/LICENSE.TXT ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/include/__libunwind_config.h =================================================================== --- head/contrib/libunwind/include/__libunwind_config.h (nonexistent) +++ head/contrib/libunwind/include/__libunwind_config.h (revision 345068) @@ -0,0 +1,148 @@ +//===------------------------- __libunwind_config.h -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef ____LIBUNWIND_CONFIG_H__ +#define ____LIBUNWIND_CONFIG_H__ + +#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ + !defined(__ARM_DWARF_EH__) +#define _LIBUNWIND_ARM_EHABI +#endif + +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 8 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 32 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC 112 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64 116 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 95 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM 287 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 32 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 95 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC 31 + +#if defined(_LIBUNWIND_IS_NATIVE_ONLY) +# if defined(__i386__) +# define _LIBUNWIND_TARGET_I386 +# define _LIBUNWIND_CONTEXT_SIZE 8 +# define _LIBUNWIND_CURSOR_SIZE 15 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 +# elif defined(__x86_64__) +# define _LIBUNWIND_TARGET_X86_64 1 +# if defined(_WIN64) +# define _LIBUNWIND_CONTEXT_SIZE 54 +# ifdef __SEH__ +# define _LIBUNWIND_CURSOR_SIZE 204 +# else +# define _LIBUNWIND_CURSOR_SIZE 66 +# endif +# else +# define _LIBUNWIND_CONTEXT_SIZE 21 +# define _LIBUNWIND_CURSOR_SIZE 33 +# endif +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 +# elif defined(__powerpc64__) +# define _LIBUNWIND_TARGET_PPC64 1 +# define _LIBUNWIND_CONTEXT_SIZE 167 +# define _LIBUNWIND_CURSOR_SIZE 179 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64 +# elif defined(__ppc__) +# define _LIBUNWIND_TARGET_PPC 1 +# define _LIBUNWIND_CONTEXT_SIZE 117 +# define _LIBUNWIND_CURSOR_SIZE 124 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC +# elif defined(__aarch64__) +# define _LIBUNWIND_TARGET_AARCH64 1 +# define _LIBUNWIND_CONTEXT_SIZE 66 +# if defined(__SEH__) +# define _LIBUNWIND_CURSOR_SIZE 164 +# else +# define _LIBUNWIND_CURSOR_SIZE 78 +# endif +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 +# elif defined(__arm__) +# define _LIBUNWIND_TARGET_ARM 1 +# if defined(__SEH__) +# define _LIBUNWIND_CONTEXT_SIZE 42 +# define _LIBUNWIND_CURSOR_SIZE 80 +# elif defined(__ARM_WMMX) +# define _LIBUNWIND_CONTEXT_SIZE 61 +# define _LIBUNWIND_CURSOR_SIZE 68 +# else +# define _LIBUNWIND_CONTEXT_SIZE 42 +# define _LIBUNWIND_CURSOR_SIZE 49 +# endif +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM +# elif defined(__or1k__) +# define _LIBUNWIND_TARGET_OR1K 1 +# define _LIBUNWIND_CONTEXT_SIZE 16 +# define _LIBUNWIND_CURSOR_SIZE 24 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K +# elif defined(__riscv) +# define _LIBUNWIND_TARGET_RISCV 1 +# define _LIBUNWIND_CONTEXT_SIZE 64 +# define _LIBUNWIND_CURSOR_SIZE 76 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV +# define _LIBUNWIND_MAX_REGISTER 96 +# elif defined(__mips__) +# if defined(_ABIO32) && _MIPS_SIM == _ABIO32 +# define _LIBUNWIND_TARGET_MIPS_O32 1 +# if defined(__mips_hard_float) +# define _LIBUNWIND_CONTEXT_SIZE 50 +# define _LIBUNWIND_CURSOR_SIZE 57 +# else +# define _LIBUNWIND_CONTEXT_SIZE 18 +# define _LIBUNWIND_CURSOR_SIZE 24 +# endif +# elif defined(_ABIN32) && _MIPS_SIM == _ABIN32 +# define _LIBUNWIND_TARGET_MIPS_NEWABI 1 +# if defined(__mips_hard_float) +# define _LIBUNWIND_CONTEXT_SIZE 67 +# define _LIBUNWIND_CURSOR_SIZE 74 +# else +# define _LIBUNWIND_CONTEXT_SIZE 35 +# define _LIBUNWIND_CURSOR_SIZE 42 +# endif +# elif defined(_ABI64) && _MIPS_SIM == _ABI64 +# define _LIBUNWIND_TARGET_MIPS_NEWABI 1 +# if defined(__mips_hard_float) +# define _LIBUNWIND_CONTEXT_SIZE 67 +# define _LIBUNWIND_CURSOR_SIZE 79 +# else +# define _LIBUNWIND_CONTEXT_SIZE 35 +# define _LIBUNWIND_CURSOR_SIZE 47 +# endif +# else +# error "Unsupported MIPS ABI and/or environment" +# endif +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS +# elif defined(__sparc__) + #define _LIBUNWIND_TARGET_SPARC 1 + #define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC + #define _LIBUNWIND_CONTEXT_SIZE 16 + #define _LIBUNWIND_CURSOR_SIZE 23 +# else +# error "Unsupported architecture." +# endif +#else // !_LIBUNWIND_IS_NATIVE_ONLY +# define _LIBUNWIND_TARGET_I386 +# define _LIBUNWIND_TARGET_X86_64 1 +# define _LIBUNWIND_TARGET_PPC 1 +# define _LIBUNWIND_TARGET_PPC64 1 +# define _LIBUNWIND_TARGET_AARCH64 1 +# define _LIBUNWIND_TARGET_ARM 1 +# define _LIBUNWIND_TARGET_OR1K 1 +# define _LIBUNWIND_TARGET_MIPS_O32 1 +# define _LIBUNWIND_TARGET_MIPS_NEWABI 1 +# define _LIBUNWIND_TARGET_SPARC 1 +# define _LIBUNWIND_CONTEXT_SIZE 167 +# define _LIBUNWIND_CURSOR_SIZE 179 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287 +#endif // _LIBUNWIND_IS_NATIVE_ONLY + +#endif // ____LIBUNWIND_CONFIG_H__ Property changes on: head/contrib/libunwind/include/__libunwind_config.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/include/libunwind.h =================================================================== --- head/contrib/libunwind/include/libunwind.h (nonexistent) +++ head/contrib/libunwind/include/libunwind.h (revision 345068) @@ -0,0 +1,933 @@ +//===---------------------------- libunwind.h -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Compatible with libunwind API documented at: +// http://www.nongnu.org/libunwind/man/libunwind(3).html +// +//===----------------------------------------------------------------------===// + +#ifndef __LIBUNWIND__ +#define __LIBUNWIND__ + +#include <__libunwind_config.h> + +#include +#include + +#ifdef __APPLE__ + #if __clang__ + #if __has_include() + #include + #endif + #elif __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 + #include + #endif + + #ifdef __arm__ + #define LIBUNWIND_AVAIL __attribute__((unavailable)) + #elif defined(__OSX_AVAILABLE_STARTING) + #define LIBUNWIND_AVAIL __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0) + #else + #include + #ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER + #define LIBUNWIND_AVAIL AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER + #else + #define LIBUNWIND_AVAIL __attribute__((unavailable)) + #endif + #endif +#else + #define LIBUNWIND_AVAIL +#endif + +/* error codes */ +enum { + UNW_ESUCCESS = 0, /* no error */ + UNW_EUNSPEC = -6540, /* unspecified (general) error */ + UNW_ENOMEM = -6541, /* out of memory */ + UNW_EBADREG = -6542, /* bad register number */ + UNW_EREADONLYREG = -6543, /* attempt to write read-only register */ + UNW_ESTOPUNWIND = -6544, /* stop unwinding */ + UNW_EINVALIDIP = -6545, /* invalid IP */ + UNW_EBADFRAME = -6546, /* bad frame */ + UNW_EINVAL = -6547, /* unsupported operation or bad value */ + UNW_EBADVERSION = -6548, /* unwind info has unsupported version */ + UNW_ENOINFO = -6549 /* no unwind info found */ +#if defined(_LIBUNWIND_TARGET_AARCH64) && !defined(_LIBUNWIND_IS_NATIVE_ONLY) + , UNW_ECROSSRASIGNING = -6550 /* cross unwind with return address signing */ +#endif +}; + +struct unw_context_t { + uint64_t data[_LIBUNWIND_CONTEXT_SIZE]; +}; +typedef struct unw_context_t unw_context_t; + +struct unw_cursor_t { + uint64_t data[_LIBUNWIND_CURSOR_SIZE]; +}; +typedef struct unw_cursor_t unw_cursor_t; + +typedef struct unw_addr_space *unw_addr_space_t; + +typedef int unw_regnum_t; +typedef uintptr_t unw_word_t; +#if defined(__arm__) +typedef uint64_t unw_fpreg_t; +#else +typedef double unw_fpreg_t; +#endif + +struct unw_proc_info_t { + unw_word_t start_ip; /* start address of function */ + unw_word_t end_ip; /* address after end of function */ + unw_word_t lsda; /* address of language specific data area, */ + /* or zero if not used */ + unw_word_t handler; /* personality routine, or zero if not used */ + unw_word_t gp; /* not used */ + unw_word_t flags; /* not used */ + uint32_t format; /* compact unwind encoding, or zero if none */ + uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */ + unw_word_t unwind_info; /* address of DWARF unwind info, or zero */ + unw_word_t extra; /* mach_header of mach-o image containing func */ +}; +typedef struct unw_proc_info_t unw_proc_info_t; + +#ifdef __cplusplus +extern "C" { +#endif + +extern int unw_getcontext(unw_context_t *) LIBUNWIND_AVAIL; +extern int unw_init_local(unw_cursor_t *, unw_context_t *) LIBUNWIND_AVAIL; +extern int unw_step(unw_cursor_t *) LIBUNWIND_AVAIL; +extern int unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *) LIBUNWIND_AVAIL; +extern int unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *) LIBUNWIND_AVAIL; +extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t) LIBUNWIND_AVAIL; +extern int unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t) LIBUNWIND_AVAIL; +extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL; + +#ifdef __arm__ +/* Save VFP registers in FSTMX format (instead of FSTMD). */ +extern void unw_save_vfp_as_X(unw_cursor_t *) LIBUNWIND_AVAIL; +#endif + + +extern const char *unw_regname(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL; +extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL; +extern int unw_is_fpreg(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL; +extern int unw_is_signal_frame(unw_cursor_t *) LIBUNWIND_AVAIL; +extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUNWIND_AVAIL; +//extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*); + +extern unw_addr_space_t unw_local_addr_space; + +#ifdef UNW_REMOTE +/* + * Mac OS X "remote" API for unwinding other processes on same machine + * + */ +extern unw_addr_space_t unw_create_addr_space_for_task(task_t); +extern void unw_destroy_addr_space(unw_addr_space_t); +extern int unw_init_remote_thread(unw_cursor_t *, unw_addr_space_t, thread_t *); +#endif /* UNW_REMOTE */ + +/* + * traditional libunwind "remote" API + * NOT IMPLEMENTED on Mac OS X + * + * extern int unw_init_remote(unw_cursor_t*, unw_addr_space_t, + * thread_t*); + * extern unw_accessors_t unw_get_accessors(unw_addr_space_t); + * extern unw_addr_space_t unw_create_addr_space(unw_accessors_t, int); + * extern void unw_flush_cache(unw_addr_space_t, unw_word_t, + * unw_word_t); + * extern int unw_set_caching_policy(unw_addr_space_t, + * unw_caching_policy_t); + * extern void _U_dyn_register(unw_dyn_info_t*); + * extern void _U_dyn_cancel(unw_dyn_info_t*); + */ + +#ifdef __cplusplus +} +#endif + +// architecture independent register numbers +enum { + UNW_REG_IP = -1, // instruction pointer + UNW_REG_SP = -2, // stack pointer +}; + +// 32-bit x86 registers +enum { + UNW_X86_EAX = 0, + UNW_X86_ECX = 1, + UNW_X86_EDX = 2, + UNW_X86_EBX = 3, + UNW_X86_EBP = 4, + UNW_X86_ESP = 5, + UNW_X86_ESI = 6, + UNW_X86_EDI = 7 +}; + +// 64-bit x86_64 registers +enum { + UNW_X86_64_RAX = 0, + UNW_X86_64_RDX = 1, + UNW_X86_64_RCX = 2, + UNW_X86_64_RBX = 3, + UNW_X86_64_RSI = 4, + UNW_X86_64_RDI = 5, + UNW_X86_64_RBP = 6, + UNW_X86_64_RSP = 7, + UNW_X86_64_R8 = 8, + UNW_X86_64_R9 = 9, + UNW_X86_64_R10 = 10, + UNW_X86_64_R11 = 11, + UNW_X86_64_R12 = 12, + UNW_X86_64_R13 = 13, + UNW_X86_64_R14 = 14, + UNW_X86_64_R15 = 15, + UNW_X86_64_RIP = 16, + UNW_X86_64_XMM0 = 17, + UNW_X86_64_XMM1 = 18, + UNW_X86_64_XMM2 = 19, + UNW_X86_64_XMM3 = 20, + UNW_X86_64_XMM4 = 21, + UNW_X86_64_XMM5 = 22, + UNW_X86_64_XMM6 = 23, + UNW_X86_64_XMM7 = 24, + UNW_X86_64_XMM8 = 25, + UNW_X86_64_XMM9 = 26, + UNW_X86_64_XMM10 = 27, + UNW_X86_64_XMM11 = 28, + UNW_X86_64_XMM12 = 29, + UNW_X86_64_XMM13 = 30, + UNW_X86_64_XMM14 = 31, + UNW_X86_64_XMM15 = 32, +}; + + +// 32-bit ppc register numbers +enum { + UNW_PPC_R0 = 0, + UNW_PPC_R1 = 1, + UNW_PPC_R2 = 2, + UNW_PPC_R3 = 3, + UNW_PPC_R4 = 4, + UNW_PPC_R5 = 5, + UNW_PPC_R6 = 6, + UNW_PPC_R7 = 7, + UNW_PPC_R8 = 8, + UNW_PPC_R9 = 9, + UNW_PPC_R10 = 10, + UNW_PPC_R11 = 11, + UNW_PPC_R12 = 12, + UNW_PPC_R13 = 13, + UNW_PPC_R14 = 14, + UNW_PPC_R15 = 15, + UNW_PPC_R16 = 16, + UNW_PPC_R17 = 17, + UNW_PPC_R18 = 18, + UNW_PPC_R19 = 19, + UNW_PPC_R20 = 20, + UNW_PPC_R21 = 21, + UNW_PPC_R22 = 22, + UNW_PPC_R23 = 23, + UNW_PPC_R24 = 24, + UNW_PPC_R25 = 25, + UNW_PPC_R26 = 26, + UNW_PPC_R27 = 27, + UNW_PPC_R28 = 28, + UNW_PPC_R29 = 29, + UNW_PPC_R30 = 30, + UNW_PPC_R31 = 31, + UNW_PPC_F0 = 32, + UNW_PPC_F1 = 33, + UNW_PPC_F2 = 34, + UNW_PPC_F3 = 35, + UNW_PPC_F4 = 36, + UNW_PPC_F5 = 37, + UNW_PPC_F6 = 38, + UNW_PPC_F7 = 39, + UNW_PPC_F8 = 40, + UNW_PPC_F9 = 41, + UNW_PPC_F10 = 42, + UNW_PPC_F11 = 43, + UNW_PPC_F12 = 44, + UNW_PPC_F13 = 45, + UNW_PPC_F14 = 46, + UNW_PPC_F15 = 47, + UNW_PPC_F16 = 48, + UNW_PPC_F17 = 49, + UNW_PPC_F18 = 50, + UNW_PPC_F19 = 51, + UNW_PPC_F20 = 52, + UNW_PPC_F21 = 53, + UNW_PPC_F22 = 54, + UNW_PPC_F23 = 55, + UNW_PPC_F24 = 56, + UNW_PPC_F25 = 57, + UNW_PPC_F26 = 58, + UNW_PPC_F27 = 59, + UNW_PPC_F28 = 60, + UNW_PPC_F29 = 61, + UNW_PPC_F30 = 62, + UNW_PPC_F31 = 63, + UNW_PPC_MQ = 64, + UNW_PPC_LR = 65, + UNW_PPC_CTR = 66, + UNW_PPC_AP = 67, + UNW_PPC_CR0 = 68, + UNW_PPC_CR1 = 69, + UNW_PPC_CR2 = 70, + UNW_PPC_CR3 = 71, + UNW_PPC_CR4 = 72, + UNW_PPC_CR5 = 73, + UNW_PPC_CR6 = 74, + UNW_PPC_CR7 = 75, + UNW_PPC_XER = 76, + UNW_PPC_V0 = 77, + UNW_PPC_V1 = 78, + UNW_PPC_V2 = 79, + UNW_PPC_V3 = 80, + UNW_PPC_V4 = 81, + UNW_PPC_V5 = 82, + UNW_PPC_V6 = 83, + UNW_PPC_V7 = 84, + UNW_PPC_V8 = 85, + UNW_PPC_V9 = 86, + UNW_PPC_V10 = 87, + UNW_PPC_V11 = 88, + UNW_PPC_V12 = 89, + UNW_PPC_V13 = 90, + UNW_PPC_V14 = 91, + UNW_PPC_V15 = 92, + UNW_PPC_V16 = 93, + UNW_PPC_V17 = 94, + UNW_PPC_V18 = 95, + UNW_PPC_V19 = 96, + UNW_PPC_V20 = 97, + UNW_PPC_V21 = 98, + UNW_PPC_V22 = 99, + UNW_PPC_V23 = 100, + UNW_PPC_V24 = 101, + UNW_PPC_V25 = 102, + UNW_PPC_V26 = 103, + UNW_PPC_V27 = 104, + UNW_PPC_V28 = 105, + UNW_PPC_V29 = 106, + UNW_PPC_V30 = 107, + UNW_PPC_V31 = 108, + UNW_PPC_VRSAVE = 109, + UNW_PPC_VSCR = 110, + UNW_PPC_SPE_ACC = 111, + UNW_PPC_SPEFSCR = 112 +}; + +// 64-bit ppc register numbers +enum { + UNW_PPC64_R0 = 0, + UNW_PPC64_R1 = 1, + UNW_PPC64_R2 = 2, + UNW_PPC64_R3 = 3, + UNW_PPC64_R4 = 4, + UNW_PPC64_R5 = 5, + UNW_PPC64_R6 = 6, + UNW_PPC64_R7 = 7, + UNW_PPC64_R8 = 8, + UNW_PPC64_R9 = 9, + UNW_PPC64_R10 = 10, + UNW_PPC64_R11 = 11, + UNW_PPC64_R12 = 12, + UNW_PPC64_R13 = 13, + UNW_PPC64_R14 = 14, + UNW_PPC64_R15 = 15, + UNW_PPC64_R16 = 16, + UNW_PPC64_R17 = 17, + UNW_PPC64_R18 = 18, + UNW_PPC64_R19 = 19, + UNW_PPC64_R20 = 20, + UNW_PPC64_R21 = 21, + UNW_PPC64_R22 = 22, + UNW_PPC64_R23 = 23, + UNW_PPC64_R24 = 24, + UNW_PPC64_R25 = 25, + UNW_PPC64_R26 = 26, + UNW_PPC64_R27 = 27, + UNW_PPC64_R28 = 28, + UNW_PPC64_R29 = 29, + UNW_PPC64_R30 = 30, + UNW_PPC64_R31 = 31, + UNW_PPC64_F0 = 32, + UNW_PPC64_F1 = 33, + UNW_PPC64_F2 = 34, + UNW_PPC64_F3 = 35, + UNW_PPC64_F4 = 36, + UNW_PPC64_F5 = 37, + UNW_PPC64_F6 = 38, + UNW_PPC64_F7 = 39, + UNW_PPC64_F8 = 40, + UNW_PPC64_F9 = 41, + UNW_PPC64_F10 = 42, + UNW_PPC64_F11 = 43, + UNW_PPC64_F12 = 44, + UNW_PPC64_F13 = 45, + UNW_PPC64_F14 = 46, + UNW_PPC64_F15 = 47, + UNW_PPC64_F16 = 48, + UNW_PPC64_F17 = 49, + UNW_PPC64_F18 = 50, + UNW_PPC64_F19 = 51, + UNW_PPC64_F20 = 52, + UNW_PPC64_F21 = 53, + UNW_PPC64_F22 = 54, + UNW_PPC64_F23 = 55, + UNW_PPC64_F24 = 56, + UNW_PPC64_F25 = 57, + UNW_PPC64_F26 = 58, + UNW_PPC64_F27 = 59, + UNW_PPC64_F28 = 60, + UNW_PPC64_F29 = 61, + UNW_PPC64_F30 = 62, + UNW_PPC64_F31 = 63, + // 64: reserved + UNW_PPC64_LR = 65, + UNW_PPC64_CTR = 66, + // 67: reserved + UNW_PPC64_CR0 = 68, + UNW_PPC64_CR1 = 69, + UNW_PPC64_CR2 = 70, + UNW_PPC64_CR3 = 71, + UNW_PPC64_CR4 = 72, + UNW_PPC64_CR5 = 73, + UNW_PPC64_CR6 = 74, + UNW_PPC64_CR7 = 75, + UNW_PPC64_XER = 76, + UNW_PPC64_V0 = 77, + UNW_PPC64_V1 = 78, + UNW_PPC64_V2 = 79, + UNW_PPC64_V3 = 80, + UNW_PPC64_V4 = 81, + UNW_PPC64_V5 = 82, + UNW_PPC64_V6 = 83, + UNW_PPC64_V7 = 84, + UNW_PPC64_V8 = 85, + UNW_PPC64_V9 = 86, + UNW_PPC64_V10 = 87, + UNW_PPC64_V11 = 88, + UNW_PPC64_V12 = 89, + UNW_PPC64_V13 = 90, + UNW_PPC64_V14 = 91, + UNW_PPC64_V15 = 92, + UNW_PPC64_V16 = 93, + UNW_PPC64_V17 = 94, + UNW_PPC64_V18 = 95, + UNW_PPC64_V19 = 96, + UNW_PPC64_V20 = 97, + UNW_PPC64_V21 = 98, + UNW_PPC64_V22 = 99, + UNW_PPC64_V23 = 100, + UNW_PPC64_V24 = 101, + UNW_PPC64_V25 = 102, + UNW_PPC64_V26 = 103, + UNW_PPC64_V27 = 104, + UNW_PPC64_V28 = 105, + UNW_PPC64_V29 = 106, + UNW_PPC64_V30 = 107, + UNW_PPC64_V31 = 108, + // 109, 111-113: OpenPOWER ELF V2 ABI: reserved + // Borrowing VRSAVE number from PPC32. + UNW_PPC64_VRSAVE = 109, + UNW_PPC64_VSCR = 110, + UNW_PPC64_TFHAR = 114, + UNW_PPC64_TFIAR = 115, + UNW_PPC64_TEXASR = 116, + UNW_PPC64_VS0 = UNW_PPC64_F0, + UNW_PPC64_VS1 = UNW_PPC64_F1, + UNW_PPC64_VS2 = UNW_PPC64_F2, + UNW_PPC64_VS3 = UNW_PPC64_F3, + UNW_PPC64_VS4 = UNW_PPC64_F4, + UNW_PPC64_VS5 = UNW_PPC64_F5, + UNW_PPC64_VS6 = UNW_PPC64_F6, + UNW_PPC64_VS7 = UNW_PPC64_F7, + UNW_PPC64_VS8 = UNW_PPC64_F8, + UNW_PPC64_VS9 = UNW_PPC64_F9, + UNW_PPC64_VS10 = UNW_PPC64_F10, + UNW_PPC64_VS11 = UNW_PPC64_F11, + UNW_PPC64_VS12 = UNW_PPC64_F12, + UNW_PPC64_VS13 = UNW_PPC64_F13, + UNW_PPC64_VS14 = UNW_PPC64_F14, + UNW_PPC64_VS15 = UNW_PPC64_F15, + UNW_PPC64_VS16 = UNW_PPC64_F16, + UNW_PPC64_VS17 = UNW_PPC64_F17, + UNW_PPC64_VS18 = UNW_PPC64_F18, + UNW_PPC64_VS19 = UNW_PPC64_F19, + UNW_PPC64_VS20 = UNW_PPC64_F20, + UNW_PPC64_VS21 = UNW_PPC64_F21, + UNW_PPC64_VS22 = UNW_PPC64_F22, + UNW_PPC64_VS23 = UNW_PPC64_F23, + UNW_PPC64_VS24 = UNW_PPC64_F24, + UNW_PPC64_VS25 = UNW_PPC64_F25, + UNW_PPC64_VS26 = UNW_PPC64_F26, + UNW_PPC64_VS27 = UNW_PPC64_F27, + UNW_PPC64_VS28 = UNW_PPC64_F28, + UNW_PPC64_VS29 = UNW_PPC64_F29, + UNW_PPC64_VS30 = UNW_PPC64_F30, + UNW_PPC64_VS31 = UNW_PPC64_F31, + UNW_PPC64_VS32 = UNW_PPC64_V0, + UNW_PPC64_VS33 = UNW_PPC64_V1, + UNW_PPC64_VS34 = UNW_PPC64_V2, + UNW_PPC64_VS35 = UNW_PPC64_V3, + UNW_PPC64_VS36 = UNW_PPC64_V4, + UNW_PPC64_VS37 = UNW_PPC64_V5, + UNW_PPC64_VS38 = UNW_PPC64_V6, + UNW_PPC64_VS39 = UNW_PPC64_V7, + UNW_PPC64_VS40 = UNW_PPC64_V8, + UNW_PPC64_VS41 = UNW_PPC64_V9, + UNW_PPC64_VS42 = UNW_PPC64_V10, + UNW_PPC64_VS43 = UNW_PPC64_V11, + UNW_PPC64_VS44 = UNW_PPC64_V12, + UNW_PPC64_VS45 = UNW_PPC64_V13, + UNW_PPC64_VS46 = UNW_PPC64_V14, + UNW_PPC64_VS47 = UNW_PPC64_V15, + UNW_PPC64_VS48 = UNW_PPC64_V16, + UNW_PPC64_VS49 = UNW_PPC64_V17, + UNW_PPC64_VS50 = UNW_PPC64_V18, + UNW_PPC64_VS51 = UNW_PPC64_V19, + UNW_PPC64_VS52 = UNW_PPC64_V20, + UNW_PPC64_VS53 = UNW_PPC64_V21, + UNW_PPC64_VS54 = UNW_PPC64_V22, + UNW_PPC64_VS55 = UNW_PPC64_V23, + UNW_PPC64_VS56 = UNW_PPC64_V24, + UNW_PPC64_VS57 = UNW_PPC64_V25, + UNW_PPC64_VS58 = UNW_PPC64_V26, + UNW_PPC64_VS59 = UNW_PPC64_V27, + UNW_PPC64_VS60 = UNW_PPC64_V28, + UNW_PPC64_VS61 = UNW_PPC64_V29, + UNW_PPC64_VS62 = UNW_PPC64_V30, + UNW_PPC64_VS63 = UNW_PPC64_V31 +}; + +// 64-bit ARM64 registers +enum { + UNW_ARM64_X0 = 0, + UNW_ARM64_X1 = 1, + UNW_ARM64_X2 = 2, + UNW_ARM64_X3 = 3, + UNW_ARM64_X4 = 4, + UNW_ARM64_X5 = 5, + UNW_ARM64_X6 = 6, + UNW_ARM64_X7 = 7, + UNW_ARM64_X8 = 8, + UNW_ARM64_X9 = 9, + UNW_ARM64_X10 = 10, + UNW_ARM64_X11 = 11, + UNW_ARM64_X12 = 12, + UNW_ARM64_X13 = 13, + UNW_ARM64_X14 = 14, + UNW_ARM64_X15 = 15, + UNW_ARM64_X16 = 16, + UNW_ARM64_X17 = 17, + UNW_ARM64_X18 = 18, + UNW_ARM64_X19 = 19, + UNW_ARM64_X20 = 20, + UNW_ARM64_X21 = 21, + UNW_ARM64_X22 = 22, + UNW_ARM64_X23 = 23, + UNW_ARM64_X24 = 24, + UNW_ARM64_X25 = 25, + UNW_ARM64_X26 = 26, + UNW_ARM64_X27 = 27, + UNW_ARM64_X28 = 28, + UNW_ARM64_X29 = 29, + UNW_ARM64_FP = 29, + UNW_ARM64_X30 = 30, + UNW_ARM64_LR = 30, + UNW_ARM64_X31 = 31, + UNW_ARM64_SP = 31, + // reserved block + UNW_ARM64_RA_SIGN_STATE = 34, + // reserved block + UNW_ARM64_D0 = 64, + UNW_ARM64_D1 = 65, + UNW_ARM64_D2 = 66, + UNW_ARM64_D3 = 67, + UNW_ARM64_D4 = 68, + UNW_ARM64_D5 = 69, + UNW_ARM64_D6 = 70, + UNW_ARM64_D7 = 71, + UNW_ARM64_D8 = 72, + UNW_ARM64_D9 = 73, + UNW_ARM64_D10 = 74, + UNW_ARM64_D11 = 75, + UNW_ARM64_D12 = 76, + UNW_ARM64_D13 = 77, + UNW_ARM64_D14 = 78, + UNW_ARM64_D15 = 79, + UNW_ARM64_D16 = 80, + UNW_ARM64_D17 = 81, + UNW_ARM64_D18 = 82, + UNW_ARM64_D19 = 83, + UNW_ARM64_D20 = 84, + UNW_ARM64_D21 = 85, + UNW_ARM64_D22 = 86, + UNW_ARM64_D23 = 87, + UNW_ARM64_D24 = 88, + UNW_ARM64_D25 = 89, + UNW_ARM64_D26 = 90, + UNW_ARM64_D27 = 91, + UNW_ARM64_D28 = 92, + UNW_ARM64_D29 = 93, + UNW_ARM64_D30 = 94, + UNW_ARM64_D31 = 95, +}; + +// 32-bit ARM registers. Numbers match DWARF for ARM spec #3.1 Table 1. +// Naming scheme uses recommendations given in Note 4 for VFP-v2 and VFP-v3. +// In this scheme, even though the 64-bit floating point registers D0-D31 +// overlap physically with the 32-bit floating pointer registers S0-S31, +// they are given a non-overlapping range of register numbers. +// +// Commented out ranges are not preserved during unwinding. +enum { + UNW_ARM_R0 = 0, + UNW_ARM_R1 = 1, + UNW_ARM_R2 = 2, + UNW_ARM_R3 = 3, + UNW_ARM_R4 = 4, + UNW_ARM_R5 = 5, + UNW_ARM_R6 = 6, + UNW_ARM_R7 = 7, + UNW_ARM_R8 = 8, + UNW_ARM_R9 = 9, + UNW_ARM_R10 = 10, + UNW_ARM_R11 = 11, + UNW_ARM_R12 = 12, + UNW_ARM_SP = 13, // Logical alias for UNW_REG_SP + UNW_ARM_R13 = 13, + UNW_ARM_LR = 14, + UNW_ARM_R14 = 14, + UNW_ARM_IP = 15, // Logical alias for UNW_REG_IP + UNW_ARM_R15 = 15, + // 16-63 -- OBSOLETE. Used in VFP1 to represent both S0-S31 and D0-D31. + UNW_ARM_S0 = 64, + UNW_ARM_S1 = 65, + UNW_ARM_S2 = 66, + UNW_ARM_S3 = 67, + UNW_ARM_S4 = 68, + UNW_ARM_S5 = 69, + UNW_ARM_S6 = 70, + UNW_ARM_S7 = 71, + UNW_ARM_S8 = 72, + UNW_ARM_S9 = 73, + UNW_ARM_S10 = 74, + UNW_ARM_S11 = 75, + UNW_ARM_S12 = 76, + UNW_ARM_S13 = 77, + UNW_ARM_S14 = 78, + UNW_ARM_S15 = 79, + UNW_ARM_S16 = 80, + UNW_ARM_S17 = 81, + UNW_ARM_S18 = 82, + UNW_ARM_S19 = 83, + UNW_ARM_S20 = 84, + UNW_ARM_S21 = 85, + UNW_ARM_S22 = 86, + UNW_ARM_S23 = 87, + UNW_ARM_S24 = 88, + UNW_ARM_S25 = 89, + UNW_ARM_S26 = 90, + UNW_ARM_S27 = 91, + UNW_ARM_S28 = 92, + UNW_ARM_S29 = 93, + UNW_ARM_S30 = 94, + UNW_ARM_S31 = 95, + // 96-103 -- OBSOLETE. F0-F7. Used by the FPA system. Superseded by VFP. + // 104-111 -- wCGR0-wCGR7, ACC0-ACC7 (Intel wireless MMX) + UNW_ARM_WR0 = 112, + UNW_ARM_WR1 = 113, + UNW_ARM_WR2 = 114, + UNW_ARM_WR3 = 115, + UNW_ARM_WR4 = 116, + UNW_ARM_WR5 = 117, + UNW_ARM_WR6 = 118, + UNW_ARM_WR7 = 119, + UNW_ARM_WR8 = 120, + UNW_ARM_WR9 = 121, + UNW_ARM_WR10 = 122, + UNW_ARM_WR11 = 123, + UNW_ARM_WR12 = 124, + UNW_ARM_WR13 = 125, + UNW_ARM_WR14 = 126, + UNW_ARM_WR15 = 127, + // 128-133 -- SPSR, SPSR_{FIQ|IRQ|ABT|UND|SVC} + // 134-143 -- Reserved + // 144-150 -- R8_USR-R14_USR + // 151-157 -- R8_FIQ-R14_FIQ + // 158-159 -- R13_IRQ-R14_IRQ + // 160-161 -- R13_ABT-R14_ABT + // 162-163 -- R13_UND-R14_UND + // 164-165 -- R13_SVC-R14_SVC + // 166-191 -- Reserved + UNW_ARM_WC0 = 192, + UNW_ARM_WC1 = 193, + UNW_ARM_WC2 = 194, + UNW_ARM_WC3 = 195, + // 196-199 -- wC4-wC7 (Intel wireless MMX control) + // 200-255 -- Reserved + UNW_ARM_D0 = 256, + UNW_ARM_D1 = 257, + UNW_ARM_D2 = 258, + UNW_ARM_D3 = 259, + UNW_ARM_D4 = 260, + UNW_ARM_D5 = 261, + UNW_ARM_D6 = 262, + UNW_ARM_D7 = 263, + UNW_ARM_D8 = 264, + UNW_ARM_D9 = 265, + UNW_ARM_D10 = 266, + UNW_ARM_D11 = 267, + UNW_ARM_D12 = 268, + UNW_ARM_D13 = 269, + UNW_ARM_D14 = 270, + UNW_ARM_D15 = 271, + UNW_ARM_D16 = 272, + UNW_ARM_D17 = 273, + UNW_ARM_D18 = 274, + UNW_ARM_D19 = 275, + UNW_ARM_D20 = 276, + UNW_ARM_D21 = 277, + UNW_ARM_D22 = 278, + UNW_ARM_D23 = 279, + UNW_ARM_D24 = 280, + UNW_ARM_D25 = 281, + UNW_ARM_D26 = 282, + UNW_ARM_D27 = 283, + UNW_ARM_D28 = 284, + UNW_ARM_D29 = 285, + UNW_ARM_D30 = 286, + UNW_ARM_D31 = 287, + // 288-319 -- Reserved for VFP/Neon + // 320-8191 -- Reserved + // 8192-16383 -- Unspecified vendor co-processor register. +}; + +// OpenRISC1000 register numbers +enum { + UNW_OR1K_R0 = 0, + UNW_OR1K_R1 = 1, + UNW_OR1K_R2 = 2, + UNW_OR1K_R3 = 3, + UNW_OR1K_R4 = 4, + UNW_OR1K_R5 = 5, + UNW_OR1K_R6 = 6, + UNW_OR1K_R7 = 7, + UNW_OR1K_R8 = 8, + UNW_OR1K_R9 = 9, + UNW_OR1K_R10 = 10, + UNW_OR1K_R11 = 11, + UNW_OR1K_R12 = 12, + UNW_OR1K_R13 = 13, + UNW_OR1K_R14 = 14, + UNW_OR1K_R15 = 15, + UNW_OR1K_R16 = 16, + UNW_OR1K_R17 = 17, + UNW_OR1K_R18 = 18, + UNW_OR1K_R19 = 19, + UNW_OR1K_R20 = 20, + UNW_OR1K_R21 = 21, + UNW_OR1K_R22 = 22, + UNW_OR1K_R23 = 23, + UNW_OR1K_R24 = 24, + UNW_OR1K_R25 = 25, + UNW_OR1K_R26 = 26, + UNW_OR1K_R27 = 27, + UNW_OR1K_R28 = 28, + UNW_OR1K_R29 = 29, + UNW_OR1K_R30 = 30, + UNW_OR1K_R31 = 31, + UNW_OR1K_EPCR = 32, +}; + +// 64-bit RISC-V registers +enum { + UNW_RISCV_X0 = 0, + UNW_RISCV_X1 = 1, + UNW_RISCV_RA = 1, + UNW_RISCV_X2 = 2, + UNW_RISCV_SP = 2, + UNW_RISCV_X3 = 3, + UNW_RISCV_X4 = 4, + UNW_RISCV_X5 = 5, + UNW_RISCV_X6 = 6, + UNW_RISCV_X7 = 7, + UNW_RISCV_X8 = 8, + UNW_RISCV_X9 = 9, + UNW_RISCV_X10 = 10, + UNW_RISCV_X11 = 11, + UNW_RISCV_X12 = 12, + UNW_RISCV_X13 = 13, + UNW_RISCV_X14 = 14, + UNW_RISCV_X15 = 15, + UNW_RISCV_X16 = 16, + UNW_RISCV_X17 = 17, + UNW_RISCV_X18 = 18, + UNW_RISCV_X19 = 19, + UNW_RISCV_X20 = 20, + UNW_RISCV_X21 = 21, + UNW_RISCV_X22 = 22, + UNW_RISCV_X23 = 23, + UNW_RISCV_X24 = 24, + UNW_RISCV_X25 = 25, + UNW_RISCV_X26 = 26, + UNW_RISCV_X27 = 27, + UNW_RISCV_X28 = 28, + UNW_RISCV_X29 = 29, + UNW_RISCV_X30 = 30, + UNW_RISCV_X31 = 31, + // reserved block + UNW_RISCV_D0 = 64, + UNW_RISCV_D1 = 65, + UNW_RISCV_D2 = 66, + UNW_RISCV_D3 = 67, + UNW_RISCV_D4 = 68, + UNW_RISCV_D5 = 69, + UNW_RISCV_D6 = 70, + UNW_RISCV_D7 = 71, + UNW_RISCV_D8 = 72, + UNW_RISCV_D9 = 73, + UNW_RISCV_D10 = 74, + UNW_RISCV_D11 = 75, + UNW_RISCV_D12 = 76, + UNW_RISCV_D13 = 77, + UNW_RISCV_D14 = 78, + UNW_RISCV_D15 = 79, + UNW_RISCV_D16 = 80, + UNW_RISCV_D17 = 81, + UNW_RISCV_D18 = 82, + UNW_RISCV_D19 = 83, + UNW_RISCV_D20 = 84, + UNW_RISCV_D21 = 85, + UNW_RISCV_D22 = 86, + UNW_RISCV_D23 = 87, + UNW_RISCV_D24 = 88, + UNW_RISCV_D25 = 89, + UNW_RISCV_D26 = 90, + UNW_RISCV_D27 = 91, + UNW_RISCV_D28 = 92, + UNW_RISCV_D29 = 93, + UNW_RISCV_D30 = 94, + UNW_RISCV_D31 = 95, +}; + +// MIPS registers +enum { + UNW_MIPS_R0 = 0, + UNW_MIPS_R1 = 1, + UNW_MIPS_R2 = 2, + UNW_MIPS_R3 = 3, + UNW_MIPS_R4 = 4, + UNW_MIPS_R5 = 5, + UNW_MIPS_R6 = 6, + UNW_MIPS_R7 = 7, + UNW_MIPS_R8 = 8, + UNW_MIPS_R9 = 9, + UNW_MIPS_R10 = 10, + UNW_MIPS_R11 = 11, + UNW_MIPS_R12 = 12, + UNW_MIPS_R13 = 13, + UNW_MIPS_R14 = 14, + UNW_MIPS_R15 = 15, + UNW_MIPS_R16 = 16, + UNW_MIPS_R17 = 17, + UNW_MIPS_R18 = 18, + UNW_MIPS_R19 = 19, + UNW_MIPS_R20 = 20, + UNW_MIPS_R21 = 21, + UNW_MIPS_R22 = 22, + UNW_MIPS_R23 = 23, + UNW_MIPS_R24 = 24, + UNW_MIPS_R25 = 25, + UNW_MIPS_R26 = 26, + UNW_MIPS_R27 = 27, + UNW_MIPS_R28 = 28, + UNW_MIPS_R29 = 29, + UNW_MIPS_R30 = 30, + UNW_MIPS_R31 = 31, + UNW_MIPS_F0 = 32, + UNW_MIPS_F1 = 33, + UNW_MIPS_F2 = 34, + UNW_MIPS_F3 = 35, + UNW_MIPS_F4 = 36, + UNW_MIPS_F5 = 37, + UNW_MIPS_F6 = 38, + UNW_MIPS_F7 = 39, + UNW_MIPS_F8 = 40, + UNW_MIPS_F9 = 41, + UNW_MIPS_F10 = 42, + UNW_MIPS_F11 = 43, + UNW_MIPS_F12 = 44, + UNW_MIPS_F13 = 45, + UNW_MIPS_F14 = 46, + UNW_MIPS_F15 = 47, + UNW_MIPS_F16 = 48, + UNW_MIPS_F17 = 49, + UNW_MIPS_F18 = 50, + UNW_MIPS_F19 = 51, + UNW_MIPS_F20 = 52, + UNW_MIPS_F21 = 53, + UNW_MIPS_F22 = 54, + UNW_MIPS_F23 = 55, + UNW_MIPS_F24 = 56, + UNW_MIPS_F25 = 57, + UNW_MIPS_F26 = 58, + UNW_MIPS_F27 = 59, + UNW_MIPS_F28 = 60, + UNW_MIPS_F29 = 61, + UNW_MIPS_F30 = 62, + UNW_MIPS_F31 = 63, + UNW_MIPS_HI = 64, + UNW_MIPS_LO = 65, +}; + +// SPARC registers +enum { + UNW_SPARC_G0 = 0, + UNW_SPARC_G1 = 1, + UNW_SPARC_G2 = 2, + UNW_SPARC_G3 = 3, + UNW_SPARC_G4 = 4, + UNW_SPARC_G5 = 5, + UNW_SPARC_G6 = 6, + UNW_SPARC_G7 = 7, + UNW_SPARC_O0 = 8, + UNW_SPARC_O1 = 9, + UNW_SPARC_O2 = 10, + UNW_SPARC_O3 = 11, + UNW_SPARC_O4 = 12, + UNW_SPARC_O5 = 13, + UNW_SPARC_O6 = 14, + UNW_SPARC_O7 = 15, + UNW_SPARC_L0 = 16, + UNW_SPARC_L1 = 17, + UNW_SPARC_L2 = 18, + UNW_SPARC_L3 = 19, + UNW_SPARC_L4 = 20, + UNW_SPARC_L5 = 21, + UNW_SPARC_L6 = 22, + UNW_SPARC_L7 = 23, + UNW_SPARC_I0 = 24, + UNW_SPARC_I1 = 25, + UNW_SPARC_I2 = 26, + UNW_SPARC_I3 = 27, + UNW_SPARC_I4 = 28, + UNW_SPARC_I5 = 29, + UNW_SPARC_I6 = 30, + UNW_SPARC_I7 = 31, +}; + +#endif Property changes on: head/contrib/libunwind/include/libunwind.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/include/mach-o/compact_unwind_encoding.h =================================================================== --- head/contrib/libunwind/include/mach-o/compact_unwind_encoding.h (nonexistent) +++ head/contrib/libunwind/include/mach-o/compact_unwind_encoding.h (revision 345068) @@ -0,0 +1,478 @@ +//===------------------ mach-o/compact_unwind_encoding.h ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Darwin's alternative to DWARF based unwind encodings. +// +//===----------------------------------------------------------------------===// + + +#ifndef __COMPACT_UNWIND_ENCODING__ +#define __COMPACT_UNWIND_ENCODING__ + +#include + +// +// Compilers can emit standard DWARF FDEs in the __TEXT,__eh_frame section +// of object files. Or compilers can emit compact unwind information in +// the __LD,__compact_unwind section. +// +// When the linker creates a final linked image, it will create a +// __TEXT,__unwind_info section. This section is a small and fast way for the +// runtime to access unwind info for any given function. If the compiler +// emitted compact unwind info for the function, that compact unwind info will +// be encoded in the __TEXT,__unwind_info section. If the compiler emitted +// DWARF unwind info, the __TEXT,__unwind_info section will contain the offset +// of the FDE in the __TEXT,__eh_frame section in the final linked image. +// +// Note: Previously, the linker would transform some DWARF unwind infos into +// compact unwind info. But that is fragile and no longer done. + + +// +// The compact unwind endoding is a 32-bit value which encoded in an +// architecture specific way, which registers to restore from where, and how +// to unwind out of the function. +// +typedef uint32_t compact_unwind_encoding_t; + + +// architecture independent bits +enum { + UNWIND_IS_NOT_FUNCTION_START = 0x80000000, + UNWIND_HAS_LSDA = 0x40000000, + UNWIND_PERSONALITY_MASK = 0x30000000, +}; + + + + +// +// x86 +// +// 1-bit: start +// 1-bit: has lsda +// 2-bit: personality index +// +// 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=DWARF +// ebp based: +// 15-bits (5*3-bits per reg) register permutation +// 8-bits for stack offset +// frameless: +// 8-bits stack size +// 3-bits stack adjust +// 3-bits register count +// 10-bits register permutation +// +enum { + UNWIND_X86_MODE_MASK = 0x0F000000, + UNWIND_X86_MODE_EBP_FRAME = 0x01000000, + UNWIND_X86_MODE_STACK_IMMD = 0x02000000, + UNWIND_X86_MODE_STACK_IND = 0x03000000, + UNWIND_X86_MODE_DWARF = 0x04000000, + + UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF, + UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000, + + UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000, + UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000, + UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00, + UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, + + UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF, +}; + +enum { + UNWIND_X86_REG_NONE = 0, + UNWIND_X86_REG_EBX = 1, + UNWIND_X86_REG_ECX = 2, + UNWIND_X86_REG_EDX = 3, + UNWIND_X86_REG_EDI = 4, + UNWIND_X86_REG_ESI = 5, + UNWIND_X86_REG_EBP = 6, +}; + +// +// For x86 there are four modes for the compact unwind encoding: +// UNWIND_X86_MODE_EBP_FRAME: +// EBP based frame where EBP is push on stack immediately after return address, +// then ESP is moved to EBP. Thus, to unwind ESP is restored with the current +// EPB value, then EBP is restored by popping off the stack, and the return +// is done by popping the stack once more into the pc. +// All non-volatile registers that need to be restored must have been saved +// in a small range in the stack that starts EBP-4 to EBP-1020. The offset/4 +// is encoded in the UNWIND_X86_EBP_FRAME_OFFSET bits. The registers saved +// are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries. +// Each entry contains which register to restore. +// UNWIND_X86_MODE_STACK_IMMD: +// A "frameless" (EBP not used as frame pointer) function with a small +// constant stack size. To return, a constant (encoded in the compact +// unwind encoding) is added to the ESP. Then the return is done by +// popping the stack into the pc. +// All non-volatile registers that need to be restored must have been saved +// on the stack immediately after the return address. The stack_size/4 is +// encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024). +// The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT. +// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION constains which registers were +// saved and their order. +// UNWIND_X86_MODE_STACK_IND: +// A "frameless" (EBP not used as frame pointer) function large constant +// stack size. This case is like the previous, except the stack size is too +// large to encode in the compact unwind encoding. Instead it requires that +// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact +// encoding contains the offset to the nnnnnnnn value in the function in +// UNWIND_X86_FRAMELESS_STACK_SIZE. +// UNWIND_X86_MODE_DWARF: +// No compact unwind encoding is available. Instead the low 24-bits of the +// compact encoding is the offset of the DWARF FDE in the __eh_frame section. +// This mode is never used in object files. It is only generated by the +// linker in final linked images which have only DWARF unwind info for a +// function. +// +// The permutation encoding is a Lehmer code sequence encoded into a +// single variable-base number so we can encode the ordering of up to +// six registers in a 10-bit space. +// +// The following is the algorithm used to create the permutation encoding used +// with frameless stacks. It is passed the number of registers to be saved and +// an array of the register numbers saved. +// +//uint32_t permute_encode(uint32_t registerCount, const uint32_t registers[6]) +//{ +// uint32_t renumregs[6]; +// for (int i=6-registerCount; i < 6; ++i) { +// int countless = 0; +// for (int j=6-registerCount; j < i; ++j) { +// if ( registers[j] < registers[i] ) +// ++countless; +// } +// renumregs[i] = registers[i] - countless -1; +// } +// uint32_t permutationEncoding = 0; +// switch ( registerCount ) { +// case 6: +// permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] +// + 6*renumregs[2] + 2*renumregs[3] +// + renumregs[4]); +// break; +// case 5: +// permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] +// + 6*renumregs[3] + 2*renumregs[4] +// + renumregs[5]); +// break; +// case 4: +// permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] +// + 3*renumregs[4] + renumregs[5]); +// break; +// case 3: +// permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] +// + renumregs[5]); +// break; +// case 2: +// permutationEncoding |= (5*renumregs[4] + renumregs[5]); +// break; +// case 1: +// permutationEncoding |= (renumregs[5]); +// break; +// } +// return permutationEncoding; +//} +// + + + + +// +// x86_64 +// +// 1-bit: start +// 1-bit: has lsda +// 2-bit: personality index +// +// 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=DWARF +// rbp based: +// 15-bits (5*3-bits per reg) register permutation +// 8-bits for stack offset +// frameless: +// 8-bits stack size +// 3-bits stack adjust +// 3-bits register count +// 10-bits register permutation +// +enum { + UNWIND_X86_64_MODE_MASK = 0x0F000000, + UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, + UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000, + UNWIND_X86_64_MODE_STACK_IND = 0x03000000, + UNWIND_X86_64_MODE_DWARF = 0x04000000, + + UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF, + UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000, + + UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000, + UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000, + UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00, + UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, + + UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF, +}; + +enum { + UNWIND_X86_64_REG_NONE = 0, + UNWIND_X86_64_REG_RBX = 1, + UNWIND_X86_64_REG_R12 = 2, + UNWIND_X86_64_REG_R13 = 3, + UNWIND_X86_64_REG_R14 = 4, + UNWIND_X86_64_REG_R15 = 5, + UNWIND_X86_64_REG_RBP = 6, +}; +// +// For x86_64 there are four modes for the compact unwind encoding: +// UNWIND_X86_64_MODE_RBP_FRAME: +// RBP based frame where RBP is push on stack immediately after return address, +// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current +// EPB value, then RBP is restored by popping off the stack, and the return +// is done by popping the stack once more into the pc. +// All non-volatile registers that need to be restored must have been saved +// in a small range in the stack that starts RBP-8 to RBP-2040. The offset/8 +// is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits. The registers saved +// are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries. +// Each entry contains which register to restore. +// UNWIND_X86_64_MODE_STACK_IMMD: +// A "frameless" (RBP not used as frame pointer) function with a small +// constant stack size. To return, a constant (encoded in the compact +// unwind encoding) is added to the RSP. Then the return is done by +// popping the stack into the pc. +// All non-volatile registers that need to be restored must have been saved +// on the stack immediately after the return address. The stack_size/8 is +// encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048). +// The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT. +// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION constains which registers were +// saved and their order. +// UNWIND_X86_64_MODE_STACK_IND: +// A "frameless" (RBP not used as frame pointer) function large constant +// stack size. This case is like the previous, except the stack size is too +// large to encode in the compact unwind encoding. Instead it requires that +// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact +// encoding contains the offset to the nnnnnnnn value in the function in +// UNWIND_X86_64_FRAMELESS_STACK_SIZE. +// UNWIND_X86_64_MODE_DWARF: +// No compact unwind encoding is available. Instead the low 24-bits of the +// compact encoding is the offset of the DWARF FDE in the __eh_frame section. +// This mode is never used in object files. It is only generated by the +// linker in final linked images which have only DWARF unwind info for a +// function. +// + + +// ARM64 +// +// 1-bit: start +// 1-bit: has lsda +// 2-bit: personality index +// +// 4-bits: 4=frame-based, 3=DWARF, 2=frameless +// frameless: +// 12-bits of stack size +// frame-based: +// 4-bits D reg pairs saved +// 5-bits X reg pairs saved +// DWARF: +// 24-bits offset of DWARF FDE in __eh_frame section +// +enum { + UNWIND_ARM64_MODE_MASK = 0x0F000000, + UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, + UNWIND_ARM64_MODE_DWARF = 0x03000000, + UNWIND_ARM64_MODE_FRAME = 0x04000000, + + UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, + UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, + UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, + UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, + UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, + UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, + UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, + UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, + UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, + + UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, + UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, +}; +// For arm64 there are three modes for the compact unwind encoding: +// UNWIND_ARM64_MODE_FRAME: +// This is a standard arm64 prolog where FP/LR are immediately pushed on the +// stack, then SP is copied to FP. If there are any non-volatile registers +// saved, then are copied into the stack frame in pairs in a contiguous +// range right below the saved FP/LR pair. Any subset of the five X pairs +// and four D pairs can be saved, but the memory layout must be in register +// number order. +// UNWIND_ARM64_MODE_FRAMELESS: +// A "frameless" leaf function, where FP/LR are not saved. The return address +// remains in LR throughout the function. If any non-volatile registers +// are saved, they must be pushed onto the stack before any stack space is +// allocated for local variables. The stack sized (including any saved +// non-volatile registers) divided by 16 is encoded in the bits +// UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK. +// UNWIND_ARM64_MODE_DWARF: +// No compact unwind encoding is available. Instead the low 24-bits of the +// compact encoding is the offset of the DWARF FDE in the __eh_frame section. +// This mode is never used in object files. It is only generated by the +// linker in final linked images which have only DWARF unwind info for a +// function. +// + + + + + +//////////////////////////////////////////////////////////////////////////////// +// +// Relocatable Object Files: __LD,__compact_unwind +// +//////////////////////////////////////////////////////////////////////////////// + +// +// A compiler can generated compact unwind information for a function by adding +// a "row" to the __LD,__compact_unwind section. This section has the +// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers. +// It is removed by the new linker, so never ends up in final executables. +// This section is a table, initially with one row per function (that needs +// unwind info). The table columns and some conceptual entries are: +// +// range-start pointer to start of function/range +// range-length +// compact-unwind-encoding 32-bit encoding +// personality-function or zero if no personality function +// lsda or zero if no LSDA data +// +// The length and encoding fields are 32-bits. The other are all pointer sized. +// +// In x86_64 assembly, these entry would look like: +// +// .section __LD,__compact_unwind,regular,debug +// +// #compact unwind for _foo +// .quad _foo +// .set L1,LfooEnd-_foo +// .long L1 +// .long 0x01010001 +// .quad 0 +// .quad 0 +// +// #compact unwind for _bar +// .quad _bar +// .set L2,LbarEnd-_bar +// .long L2 +// .long 0x01020011 +// .quad __gxx_personality +// .quad except_tab1 +// +// +// Notes: There is no need for any labels in the the __compact_unwind section. +// The use of the .set directive is to force the evaluation of the +// range-length at assembly time, instead of generating relocations. +// +// To support future compiler optimizations where which non-volatile registers +// are saved changes within a function (e.g. delay saving non-volatiles until +// necessary), there can by multiple lines in the __compact_unwind table for one +// function, each with a different (non-overlapping) range and each with +// different compact unwind encodings that correspond to the non-volatiles +// saved at that range of the function. +// +// If a particular function is so wacky that there is no compact unwind way +// to encode it, then the compiler can emit traditional DWARF unwind info. +// The runtime will use which ever is available. +// +// Runtime support for compact unwind encodings are only available on 10.6 +// and later. So, the compiler should not generate it when targeting pre-10.6. + + + + +//////////////////////////////////////////////////////////////////////////////// +// +// Final Linked Images: __TEXT,__unwind_info +// +//////////////////////////////////////////////////////////////////////////////// + +// +// The __TEXT,__unwind_info section is laid out for an efficient two level lookup. +// The header of the section contains a coarse index that maps function address +// to the page (4096 byte block) containing the unwind info for that function. +// + +#define UNWIND_SECTION_VERSION 1 +struct unwind_info_section_header +{ + uint32_t version; // UNWIND_SECTION_VERSION + uint32_t commonEncodingsArraySectionOffset; + uint32_t commonEncodingsArrayCount; + uint32_t personalityArraySectionOffset; + uint32_t personalityArrayCount; + uint32_t indexSectionOffset; + uint32_t indexCount; + // compact_unwind_encoding_t[] + // uint32_t personalities[] + // unwind_info_section_header_index_entry[] + // unwind_info_section_header_lsda_index_entry[] +}; + +struct unwind_info_section_header_index_entry +{ + uint32_t functionOffset; + uint32_t secondLevelPagesSectionOffset; // section offset to start of regular or compress page + uint32_t lsdaIndexArraySectionOffset; // section offset to start of lsda_index array for this range +}; + +struct unwind_info_section_header_lsda_index_entry +{ + uint32_t functionOffset; + uint32_t lsdaOffset; +}; + +// +// There are two kinds of second level index pages: regular and compressed. +// A compressed page can hold up to 1021 entries, but it cannot be used +// if too many different encoding types are used. The regular page holds +// 511 entries. +// + +struct unwind_info_regular_second_level_entry +{ + uint32_t functionOffset; + compact_unwind_encoding_t encoding; +}; + +#define UNWIND_SECOND_LEVEL_REGULAR 2 +struct unwind_info_regular_second_level_page_header +{ + uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR + uint16_t entryPageOffset; + uint16_t entryCount; + // entry array +}; + +#define UNWIND_SECOND_LEVEL_COMPRESSED 3 +struct unwind_info_compressed_second_level_page_header +{ + uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED + uint16_t entryPageOffset; + uint16_t entryCount; + uint16_t encodingsPageOffset; + uint16_t encodingsCount; + // 32-bit entry array + // encodings array +}; + +#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF) +#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF) + + + +#endif + Property changes on: head/contrib/libunwind/include/mach-o/compact_unwind_encoding.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind/include/unwind.h =================================================================== --- head/contrib/libunwind/include/unwind.h (nonexistent) +++ head/contrib/libunwind/include/unwind.h (revision 345068) @@ -0,0 +1,401 @@ +//===------------------------------- unwind.h -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// C++ ABI Level 1 ABI documented at: +// http://mentorembedded.github.io/cxx-abi/abi-eh.html +// +//===----------------------------------------------------------------------===// + +#ifndef __UNWIND_H__ +#define __UNWIND_H__ + +#include <__libunwind_config.h> + +#include +#include + +#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) && defined(_WIN32) +#include +#include +#endif + +#if defined(__APPLE__) +#define LIBUNWIND_UNAVAIL __attribute__ (( unavailable )) +#else +#define LIBUNWIND_UNAVAIL +#endif + +typedef enum { + _URC_NO_REASON = 0, + _URC_OK = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8, +#if defined(_LIBUNWIND_ARM_EHABI) + _URC_FAILURE = 9 +#endif +} _Unwind_Reason_Code; + +typedef enum { + _UA_SEARCH_PHASE = 1, + _UA_CLEANUP_PHASE = 2, + _UA_HANDLER_FRAME = 4, + _UA_FORCE_UNWIND = 8, + _UA_END_OF_STACK = 16 // gcc extension to C++ ABI +} _Unwind_Action; + +typedef struct _Unwind_Context _Unwind_Context; // opaque + +#if defined(_LIBUNWIND_ARM_EHABI) +typedef uint32_t _Unwind_State; + +static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0; +static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1; +static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2; +static const _Unwind_State _US_ACTION_MASK = 3; +/* Undocumented flag for force unwinding. */ +static const _Unwind_State _US_FORCE_UNWIND = 8; + +typedef uint32_t _Unwind_EHT_Header; + +struct _Unwind_Control_Block; +typedef struct _Unwind_Control_Block _Unwind_Control_Block; +typedef struct _Unwind_Control_Block _Unwind_Exception; /* Alias */ + +struct _Unwind_Control_Block { + uint64_t exception_class; + void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block*); + + /* Unwinder cache, private fields for the unwinder's use */ + struct { + uint32_t reserved1; /* init reserved1 to 0, then don't touch */ + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + uint32_t reserved5; + } unwinder_cache; + + /* Propagation barrier cache (valid after phase 1): */ + struct { + uint32_t sp; + uint32_t bitpattern[5]; + } barrier_cache; + + /* Cleanup cache (preserved over cleanup): */ + struct { + uint32_t bitpattern[4]; + } cleanup_cache; + + /* Pr cache (for pr's benefit): */ + struct { + uint32_t fnstart; /* function start address */ + _Unwind_EHT_Header* ehtp; /* pointer to EHT entry header word */ + uint32_t additional; + uint32_t reserved1; + } pr_cache; + + long long int :0; /* Enforce the 8-byte alignment */ +} __attribute__((__aligned__(8))); + +typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) + (_Unwind_State state, + _Unwind_Exception* exceptionObject, + struct _Unwind_Context* context); + +typedef _Unwind_Reason_Code (*__personality_routine) + (_Unwind_State state, + _Unwind_Exception* exceptionObject, + struct _Unwind_Context* context); +#else +struct _Unwind_Context; // opaque +struct _Unwind_Exception; // forward declaration +typedef struct _Unwind_Exception _Unwind_Exception; + +struct _Unwind_Exception { + uint64_t exception_class; + void (*exception_cleanup)(_Unwind_Reason_Code reason, + _Unwind_Exception *exc); +#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) + uintptr_t private_[6]; +#else + uintptr_t private_1; // non-zero means forced unwind + uintptr_t private_2; // holds sp that phase1 found for phase2 to use +#endif +#if __SIZEOF_POINTER__ == 4 + // The implementation of _Unwind_Exception uses an attribute mode on the + // above fields which has the side effect of causing this whole struct to + // round up to 32 bytes in size (48 with SEH). To be more explicit, we add + // pad fields added for binary compatibility. + uint32_t reserved[3]; +#endif + // The Itanium ABI requires that _Unwind_Exception objects are "double-word + // aligned". GCC has interpreted this to mean "use the maximum useful + // alignment for the target"; so do we. +} __attribute__((__aligned__)); + +typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) + (int version, + _Unwind_Action actions, + uint64_t exceptionClass, + _Unwind_Exception* exceptionObject, + struct _Unwind_Context* context, + void* stop_parameter ); + +typedef _Unwind_Reason_Code (*__personality_routine) + (int version, + _Unwind_Action actions, + uint64_t exceptionClass, + _Unwind_Exception* exceptionObject, + struct _Unwind_Context* context); +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// +// The following are the base functions documented by the C++ ABI +// +#ifdef __USING_SJLJ_EXCEPTIONS__ +extern _Unwind_Reason_Code + _Unwind_SjLj_RaiseException(_Unwind_Exception *exception_object); +extern void _Unwind_SjLj_Resume(_Unwind_Exception *exception_object); +#else +extern _Unwind_Reason_Code + _Unwind_RaiseException(_Unwind_Exception *exception_object); +extern void _Unwind_Resume(_Unwind_Exception *exception_object); +#endif +extern void _Unwind_DeleteException(_Unwind_Exception *exception_object); + +#if defined(_LIBUNWIND_ARM_EHABI) +typedef enum { + _UVRSC_CORE = 0, /* integer register */ + _UVRSC_VFP = 1, /* vfp */ + _UVRSC_WMMXD = 3, /* Intel WMMX data register */ + _UVRSC_WMMXC = 4 /* Intel WMMX control register */ +} _Unwind_VRS_RegClass; + +typedef enum { + _UVRSD_UINT32 = 0, + _UVRSD_VFPX = 1, + _UVRSD_UINT64 = 3, + _UVRSD_FLOAT = 4, + _UVRSD_DOUBLE = 5 +} _Unwind_VRS_DataRepresentation; + +typedef enum { + _UVRSR_OK = 0, + _UVRSR_NOT_IMPLEMENTED = 1, + _UVRSR_FAILED = 2 +} _Unwind_VRS_Result; + +extern void _Unwind_Complete(_Unwind_Exception* exception_object); + +extern _Unwind_VRS_Result +_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, + uint32_t regno, _Unwind_VRS_DataRepresentation representation, + void *valuep); + +extern _Unwind_VRS_Result +_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, + uint32_t regno, _Unwind_VRS_DataRepresentation representation, + void *valuep); + +extern _Unwind_VRS_Result +_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, + uint32_t discriminator, + _Unwind_VRS_DataRepresentation representation); +#endif + +#if !defined(_LIBUNWIND_ARM_EHABI) + +extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index); +extern void _Unwind_SetGR(struct _Unwind_Context *context, int index, + uintptr_t new_value); +extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context); +extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value); + +#else // defined(_LIBUNWIND_ARM_EHABI) + +#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE) +#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern +#else +#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__ +#endif + +// These are de facto helper functions for ARM, which delegate the function +// calls to _Unwind_VRS_Get/Set(). These are not a part of ARM EHABI +// specification, thus these function MUST be inlined. Please don't replace +// these with the "extern" function declaration; otherwise, the program +// including this header won't be ABI compatible and will result in +// link error when we are linking the program with libgcc. + +_LIBUNWIND_EXPORT_UNWIND_LEVEL1 +uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { + uintptr_t value = 0; + _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); + return value; +} + +_LIBUNWIND_EXPORT_UNWIND_LEVEL1 +void _Unwind_SetGR(struct _Unwind_Context *context, int index, + uintptr_t value) { + _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); +} + +_LIBUNWIND_EXPORT_UNWIND_LEVEL1 +uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { + // remove the thumb-bit before returning + return _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1); +} + +_LIBUNWIND_EXPORT_UNWIND_LEVEL1 +void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) { + uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1); + _Unwind_SetGR(context, 15, value | thumb_bit); +} +#endif // defined(_LIBUNWIND_ARM_EHABI) + +extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context); +extern uintptr_t + _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context); +#ifdef __USING_SJLJ_EXCEPTIONS__ +extern _Unwind_Reason_Code + _Unwind_SjLj_ForcedUnwind(_Unwind_Exception *exception_object, + _Unwind_Stop_Fn stop, void *stop_parameter); +#else +extern _Unwind_Reason_Code + _Unwind_ForcedUnwind(_Unwind_Exception *exception_object, + _Unwind_Stop_Fn stop, void *stop_parameter); +#endif + +#ifdef __USING_SJLJ_EXCEPTIONS__ +typedef struct _Unwind_FunctionContext *_Unwind_FunctionContext_t; +extern void _Unwind_SjLj_Register(_Unwind_FunctionContext_t fc); +extern void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t fc); +#endif + +// +// The following are semi-suppoted extensions to the C++ ABI +// + +// +// called by __cxa_rethrow(). +// +#ifdef __USING_SJLJ_EXCEPTIONS__ +extern _Unwind_Reason_Code + _Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception *exception_object); +#else +extern _Unwind_Reason_Code + _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object); +#endif + +// _Unwind_Backtrace() is a gcc extension that walks the stack and calls the +// _Unwind_Trace_Fn once per frame until it reaches the bottom of the stack +// or the _Unwind_Trace_Fn function returns something other than _URC_NO_REASON. +typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *, + void *); +extern _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void *); + +// _Unwind_GetCFA is a gcc extension that can be called from within a +// personality handler to get the CFA (stack pointer before call) of +// current frame. +extern uintptr_t _Unwind_GetCFA(struct _Unwind_Context *); + + +// _Unwind_GetIPInfo is a gcc extension that can be called from within a +// personality handler. Similar to _Unwind_GetIP() but also returns in +// *ipBefore a non-zero value if the instruction pointer is at or before the +// instruction causing the unwind. Normally, in a function call, the IP returned +// is the return address which is after the call instruction and may be past the +// end of the function containing the call instruction. +extern uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, + int *ipBefore); + + +// __register_frame() is used with dynamically generated code to register the +// FDE for a generated (JIT) code. The FDE must use pc-rel addressing to point +// to its function and optional LSDA. +// __register_frame() has existed in all versions of Mac OS X, but in 10.4 and +// 10.5 it was buggy and did not actually register the FDE with the unwinder. +// In 10.6 and later it does register properly. +extern void __register_frame(const void *fde); +extern void __deregister_frame(const void *fde); + +// _Unwind_Find_FDE() will locate the FDE if the pc is in some function that has +// an associated FDE. Note, Mac OS X 10.6 and later, introduces "compact unwind +// info" which the runtime uses in preference to DWARF unwind info. This +// function will only work if the target function has an FDE but no compact +// unwind info. +struct dwarf_eh_bases { + uintptr_t tbase; + uintptr_t dbase; + uintptr_t func; +}; +extern const void *_Unwind_Find_FDE(const void *pc, struct dwarf_eh_bases *); + + +// This function attempts to find the start (address of first instruction) of +// a function given an address inside the function. It only works if the +// function has an FDE (DWARF unwind info). +// This function is unimplemented on Mac OS X 10.6 and later. Instead, use +// _Unwind_Find_FDE() and look at the dwarf_eh_bases.func result. +extern void *_Unwind_FindEnclosingFunction(void *pc); + +// Mac OS X does not support text-rel and data-rel addressing so these functions +// are unimplemented +extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context) + LIBUNWIND_UNAVAIL; +extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context) + LIBUNWIND_UNAVAIL; + +// Mac OS X 10.4 and 10.5 had implementations of these functions in +// libgcc_s.dylib, but they never worked. +/// These functions are no longer available on Mac OS X. +extern void __register_frame_info_bases(const void *fde, void *ob, void *tb, + void *db) LIBUNWIND_UNAVAIL; +extern void __register_frame_info(const void *fde, void *ob) + LIBUNWIND_UNAVAIL; +extern void __register_frame_info_table_bases(const void *fde, void *ob, + void *tb, void *db) + LIBUNWIND_UNAVAIL; +extern void __register_frame_info_table(const void *fde, void *ob) + LIBUNWIND_UNAVAIL; +extern void __register_frame_table(const void *fde) + LIBUNWIND_UNAVAIL; +extern void *__deregister_frame_info(const void *fde) + LIBUNWIND_UNAVAIL; +extern void *__deregister_frame_info_bases(const void *fde) + LIBUNWIND_UNAVAIL; + +#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) +#ifndef _WIN32 +typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD; +typedef struct _CONTEXT CONTEXT; +typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT; +#elif !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000 +typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT; +#endif +// This is the common wrapper for GCC-style personality functions with SEH. +extern EXCEPTION_DISPOSITION _GCC_specific_handler(EXCEPTION_RECORD *exc, + void *frame, + CONTEXT *ctx, + DISPATCHER_CONTEXT *disp, + __personality_routine pers); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // __UNWIND_H__ Property changes on: head/contrib/libunwind/include/unwind.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/libunwind =================================================================== --- head/contrib/libunwind (nonexistent) +++ head/contrib/libunwind (revision 345068) Property changes on: head/contrib/libunwind ___________________________________________________________________ Added: svn:mergeinfo ## -0,0 +0,3 ## Merged /vendor/llvm/dist/projects/libunwind:r208954-287519 Merged /vendor/llvm-libunwind/dist-release_80:r344939-345018 Merged /vendor/llvm-libunwind/dist:r288151-344967 Index: head/contrib/llvm/projects/libunwind/include/__libunwind_config.h =================================================================== --- head/contrib/llvm/projects/libunwind/include/__libunwind_config.h (revision 345067) +++ head/contrib/llvm/projects/libunwind/include/__libunwind_config.h (nonexistent) @@ -1,148 +0,0 @@ -//===------------------------- __libunwind_config.h -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef ____LIBUNWIND_CONFIG_H__ -#define ____LIBUNWIND_CONFIG_H__ - -#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ - !defined(__ARM_DWARF_EH__) -#define _LIBUNWIND_ARM_EHABI -#endif - -#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 8 -#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 32 -#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC 112 -#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64 116 -#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 95 -#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM 287 -#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 32 -#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 95 -#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65 -#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC 31 - -#if defined(_LIBUNWIND_IS_NATIVE_ONLY) -# if defined(__i386__) -# define _LIBUNWIND_TARGET_I386 -# define _LIBUNWIND_CONTEXT_SIZE 8 -# define _LIBUNWIND_CURSOR_SIZE 15 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 -# elif defined(__x86_64__) -# define _LIBUNWIND_TARGET_X86_64 1 -# if defined(_WIN64) -# define _LIBUNWIND_CONTEXT_SIZE 54 -# ifdef __SEH__ -# define _LIBUNWIND_CURSOR_SIZE 204 -# else -# define _LIBUNWIND_CURSOR_SIZE 66 -# endif -# else -# define _LIBUNWIND_CONTEXT_SIZE 21 -# define _LIBUNWIND_CURSOR_SIZE 33 -# endif -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 -# elif defined(__powerpc64__) -# define _LIBUNWIND_TARGET_PPC64 1 -# define _LIBUNWIND_CONTEXT_SIZE 167 -# define _LIBUNWIND_CURSOR_SIZE 179 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64 -# elif defined(__ppc__) -# define _LIBUNWIND_TARGET_PPC 1 -# define _LIBUNWIND_CONTEXT_SIZE 117 -# define _LIBUNWIND_CURSOR_SIZE 124 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC -# elif defined(__aarch64__) -# define _LIBUNWIND_TARGET_AARCH64 1 -# define _LIBUNWIND_CONTEXT_SIZE 66 -# if defined(__SEH__) -# define _LIBUNWIND_CURSOR_SIZE 164 -# else -# define _LIBUNWIND_CURSOR_SIZE 78 -# endif -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 -# elif defined(__arm__) -# define _LIBUNWIND_TARGET_ARM 1 -# if defined(__SEH__) -# define _LIBUNWIND_CONTEXT_SIZE 42 -# define _LIBUNWIND_CURSOR_SIZE 80 -# elif defined(__ARM_WMMX) -# define _LIBUNWIND_CONTEXT_SIZE 61 -# define _LIBUNWIND_CURSOR_SIZE 68 -# else -# define _LIBUNWIND_CONTEXT_SIZE 42 -# define _LIBUNWIND_CURSOR_SIZE 49 -# endif -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM -# elif defined(__or1k__) -# define _LIBUNWIND_TARGET_OR1K 1 -# define _LIBUNWIND_CONTEXT_SIZE 16 -# define _LIBUNWIND_CURSOR_SIZE 24 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K -# elif defined(__riscv) -# define _LIBUNWIND_TARGET_RISCV 1 -# define _LIBUNWIND_CONTEXT_SIZE 64 -# define _LIBUNWIND_CURSOR_SIZE 76 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV -# define _LIBUNWIND_MAX_REGISTER 96 -# elif defined(__mips__) -# if defined(_ABIO32) && _MIPS_SIM == _ABIO32 -# define _LIBUNWIND_TARGET_MIPS_O32 1 -# if defined(__mips_hard_float) -# define _LIBUNWIND_CONTEXT_SIZE 50 -# define _LIBUNWIND_CURSOR_SIZE 57 -# else -# define _LIBUNWIND_CONTEXT_SIZE 18 -# define _LIBUNWIND_CURSOR_SIZE 24 -# endif -# elif defined(_ABIN32) && _MIPS_SIM == _ABIN32 -# define _LIBUNWIND_TARGET_MIPS_NEWABI 1 -# if defined(__mips_hard_float) -# define _LIBUNWIND_CONTEXT_SIZE 67 -# define _LIBUNWIND_CURSOR_SIZE 74 -# else -# define _LIBUNWIND_CONTEXT_SIZE 35 -# define _LIBUNWIND_CURSOR_SIZE 42 -# endif -# elif defined(_ABI64) && _MIPS_SIM == _ABI64 -# define _LIBUNWIND_TARGET_MIPS_NEWABI 1 -# if defined(__mips_hard_float) -# define _LIBUNWIND_CONTEXT_SIZE 67 -# define _LIBUNWIND_CURSOR_SIZE 79 -# else -# define _LIBUNWIND_CONTEXT_SIZE 35 -# define _LIBUNWIND_CURSOR_SIZE 47 -# endif -# else -# error "Unsupported MIPS ABI and/or environment" -# endif -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS -# elif defined(__sparc__) - #define _LIBUNWIND_TARGET_SPARC 1 - #define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC - #define _LIBUNWIND_CONTEXT_SIZE 16 - #define _LIBUNWIND_CURSOR_SIZE 23 -# else -# error "Unsupported architecture." -# endif -#else // !_LIBUNWIND_IS_NATIVE_ONLY -# define _LIBUNWIND_TARGET_I386 -# define _LIBUNWIND_TARGET_X86_64 1 -# define _LIBUNWIND_TARGET_PPC 1 -# define _LIBUNWIND_TARGET_PPC64 1 -# define _LIBUNWIND_TARGET_AARCH64 1 -# define _LIBUNWIND_TARGET_ARM 1 -# define _LIBUNWIND_TARGET_OR1K 1 -# define _LIBUNWIND_TARGET_MIPS_O32 1 -# define _LIBUNWIND_TARGET_MIPS_NEWABI 1 -# define _LIBUNWIND_TARGET_SPARC 1 -# define _LIBUNWIND_CONTEXT_SIZE 167 -# define _LIBUNWIND_CURSOR_SIZE 179 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287 -#endif // _LIBUNWIND_IS_NATIVE_ONLY - -#endif // ____LIBUNWIND_CONFIG_H__ Property changes on: head/contrib/llvm/projects/libunwind/include/__libunwind_config.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/include/unwind.h =================================================================== --- head/contrib/llvm/projects/libunwind/include/unwind.h (revision 345067) +++ head/contrib/llvm/projects/libunwind/include/unwind.h (nonexistent) @@ -1,401 +0,0 @@ -//===------------------------------- unwind.h -----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// C++ ABI Level 1 ABI documented at: -// http://mentorembedded.github.io/cxx-abi/abi-eh.html -// -//===----------------------------------------------------------------------===// - -#ifndef __UNWIND_H__ -#define __UNWIND_H__ - -#include <__libunwind_config.h> - -#include -#include - -#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) && defined(_WIN32) -#include -#include -#endif - -#if defined(__APPLE__) -#define LIBUNWIND_UNAVAIL __attribute__ (( unavailable )) -#else -#define LIBUNWIND_UNAVAIL -#endif - -typedef enum { - _URC_NO_REASON = 0, - _URC_OK = 0, - _URC_FOREIGN_EXCEPTION_CAUGHT = 1, - _URC_FATAL_PHASE2_ERROR = 2, - _URC_FATAL_PHASE1_ERROR = 3, - _URC_NORMAL_STOP = 4, - _URC_END_OF_STACK = 5, - _URC_HANDLER_FOUND = 6, - _URC_INSTALL_CONTEXT = 7, - _URC_CONTINUE_UNWIND = 8, -#if defined(_LIBUNWIND_ARM_EHABI) - _URC_FAILURE = 9 -#endif -} _Unwind_Reason_Code; - -typedef enum { - _UA_SEARCH_PHASE = 1, - _UA_CLEANUP_PHASE = 2, - _UA_HANDLER_FRAME = 4, - _UA_FORCE_UNWIND = 8, - _UA_END_OF_STACK = 16 // gcc extension to C++ ABI -} _Unwind_Action; - -typedef struct _Unwind_Context _Unwind_Context; // opaque - -#if defined(_LIBUNWIND_ARM_EHABI) -typedef uint32_t _Unwind_State; - -static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0; -static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1; -static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2; -static const _Unwind_State _US_ACTION_MASK = 3; -/* Undocumented flag for force unwinding. */ -static const _Unwind_State _US_FORCE_UNWIND = 8; - -typedef uint32_t _Unwind_EHT_Header; - -struct _Unwind_Control_Block; -typedef struct _Unwind_Control_Block _Unwind_Control_Block; -typedef struct _Unwind_Control_Block _Unwind_Exception; /* Alias */ - -struct _Unwind_Control_Block { - uint64_t exception_class; - void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block*); - - /* Unwinder cache, private fields for the unwinder's use */ - struct { - uint32_t reserved1; /* init reserved1 to 0, then don't touch */ - uint32_t reserved2; - uint32_t reserved3; - uint32_t reserved4; - uint32_t reserved5; - } unwinder_cache; - - /* Propagation barrier cache (valid after phase 1): */ - struct { - uint32_t sp; - uint32_t bitpattern[5]; - } barrier_cache; - - /* Cleanup cache (preserved over cleanup): */ - struct { - uint32_t bitpattern[4]; - } cleanup_cache; - - /* Pr cache (for pr's benefit): */ - struct { - uint32_t fnstart; /* function start address */ - _Unwind_EHT_Header* ehtp; /* pointer to EHT entry header word */ - uint32_t additional; - uint32_t reserved1; - } pr_cache; - - long long int :0; /* Enforce the 8-byte alignment */ -} __attribute__((__aligned__(8))); - -typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) - (_Unwind_State state, - _Unwind_Exception* exceptionObject, - struct _Unwind_Context* context); - -typedef _Unwind_Reason_Code (*__personality_routine) - (_Unwind_State state, - _Unwind_Exception* exceptionObject, - struct _Unwind_Context* context); -#else -struct _Unwind_Context; // opaque -struct _Unwind_Exception; // forward declaration -typedef struct _Unwind_Exception _Unwind_Exception; - -struct _Unwind_Exception { - uint64_t exception_class; - void (*exception_cleanup)(_Unwind_Reason_Code reason, - _Unwind_Exception *exc); -#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) - uintptr_t private_[6]; -#else - uintptr_t private_1; // non-zero means forced unwind - uintptr_t private_2; // holds sp that phase1 found for phase2 to use -#endif -#if __SIZEOF_POINTER__ == 4 - // The implementation of _Unwind_Exception uses an attribute mode on the - // above fields which has the side effect of causing this whole struct to - // round up to 32 bytes in size (48 with SEH). To be more explicit, we add - // pad fields added for binary compatibility. - uint32_t reserved[3]; -#endif - // The Itanium ABI requires that _Unwind_Exception objects are "double-word - // aligned". GCC has interpreted this to mean "use the maximum useful - // alignment for the target"; so do we. -} __attribute__((__aligned__)); - -typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) - (int version, - _Unwind_Action actions, - uint64_t exceptionClass, - _Unwind_Exception* exceptionObject, - struct _Unwind_Context* context, - void* stop_parameter ); - -typedef _Unwind_Reason_Code (*__personality_routine) - (int version, - _Unwind_Action actions, - uint64_t exceptionClass, - _Unwind_Exception* exceptionObject, - struct _Unwind_Context* context); -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// -// The following are the base functions documented by the C++ ABI -// -#ifdef __USING_SJLJ_EXCEPTIONS__ -extern _Unwind_Reason_Code - _Unwind_SjLj_RaiseException(_Unwind_Exception *exception_object); -extern void _Unwind_SjLj_Resume(_Unwind_Exception *exception_object); -#else -extern _Unwind_Reason_Code - _Unwind_RaiseException(_Unwind_Exception *exception_object); -extern void _Unwind_Resume(_Unwind_Exception *exception_object); -#endif -extern void _Unwind_DeleteException(_Unwind_Exception *exception_object); - -#if defined(_LIBUNWIND_ARM_EHABI) -typedef enum { - _UVRSC_CORE = 0, /* integer register */ - _UVRSC_VFP = 1, /* vfp */ - _UVRSC_WMMXD = 3, /* Intel WMMX data register */ - _UVRSC_WMMXC = 4 /* Intel WMMX control register */ -} _Unwind_VRS_RegClass; - -typedef enum { - _UVRSD_UINT32 = 0, - _UVRSD_VFPX = 1, - _UVRSD_UINT64 = 3, - _UVRSD_FLOAT = 4, - _UVRSD_DOUBLE = 5 -} _Unwind_VRS_DataRepresentation; - -typedef enum { - _UVRSR_OK = 0, - _UVRSR_NOT_IMPLEMENTED = 1, - _UVRSR_FAILED = 2 -} _Unwind_VRS_Result; - -extern void _Unwind_Complete(_Unwind_Exception* exception_object); - -extern _Unwind_VRS_Result -_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, - uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep); - -extern _Unwind_VRS_Result -_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, - uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep); - -extern _Unwind_VRS_Result -_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, - uint32_t discriminator, - _Unwind_VRS_DataRepresentation representation); -#endif - -#if !defined(_LIBUNWIND_ARM_EHABI) - -extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index); -extern void _Unwind_SetGR(struct _Unwind_Context *context, int index, - uintptr_t new_value); -extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context); -extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value); - -#else // defined(_LIBUNWIND_ARM_EHABI) - -#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE) -#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern -#else -#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__ -#endif - -// These are de facto helper functions for ARM, which delegate the function -// calls to _Unwind_VRS_Get/Set(). These are not a part of ARM EHABI -// specification, thus these function MUST be inlined. Please don't replace -// these with the "extern" function declaration; otherwise, the program -// including this header won't be ABI compatible and will result in -// link error when we are linking the program with libgcc. - -_LIBUNWIND_EXPORT_UNWIND_LEVEL1 -uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { - uintptr_t value = 0; - _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); - return value; -} - -_LIBUNWIND_EXPORT_UNWIND_LEVEL1 -void _Unwind_SetGR(struct _Unwind_Context *context, int index, - uintptr_t value) { - _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); -} - -_LIBUNWIND_EXPORT_UNWIND_LEVEL1 -uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { - // remove the thumb-bit before returning - return _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1); -} - -_LIBUNWIND_EXPORT_UNWIND_LEVEL1 -void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) { - uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1); - _Unwind_SetGR(context, 15, value | thumb_bit); -} -#endif // defined(_LIBUNWIND_ARM_EHABI) - -extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context); -extern uintptr_t - _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context); -#ifdef __USING_SJLJ_EXCEPTIONS__ -extern _Unwind_Reason_Code - _Unwind_SjLj_ForcedUnwind(_Unwind_Exception *exception_object, - _Unwind_Stop_Fn stop, void *stop_parameter); -#else -extern _Unwind_Reason_Code - _Unwind_ForcedUnwind(_Unwind_Exception *exception_object, - _Unwind_Stop_Fn stop, void *stop_parameter); -#endif - -#ifdef __USING_SJLJ_EXCEPTIONS__ -typedef struct _Unwind_FunctionContext *_Unwind_FunctionContext_t; -extern void _Unwind_SjLj_Register(_Unwind_FunctionContext_t fc); -extern void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t fc); -#endif - -// -// The following are semi-suppoted extensions to the C++ ABI -// - -// -// called by __cxa_rethrow(). -// -#ifdef __USING_SJLJ_EXCEPTIONS__ -extern _Unwind_Reason_Code - _Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception *exception_object); -#else -extern _Unwind_Reason_Code - _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object); -#endif - -// _Unwind_Backtrace() is a gcc extension that walks the stack and calls the -// _Unwind_Trace_Fn once per frame until it reaches the bottom of the stack -// or the _Unwind_Trace_Fn function returns something other than _URC_NO_REASON. -typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *, - void *); -extern _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void *); - -// _Unwind_GetCFA is a gcc extension that can be called from within a -// personality handler to get the CFA (stack pointer before call) of -// current frame. -extern uintptr_t _Unwind_GetCFA(struct _Unwind_Context *); - - -// _Unwind_GetIPInfo is a gcc extension that can be called from within a -// personality handler. Similar to _Unwind_GetIP() but also returns in -// *ipBefore a non-zero value if the instruction pointer is at or before the -// instruction causing the unwind. Normally, in a function call, the IP returned -// is the return address which is after the call instruction and may be past the -// end of the function containing the call instruction. -extern uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, - int *ipBefore); - - -// __register_frame() is used with dynamically generated code to register the -// FDE for a generated (JIT) code. The FDE must use pc-rel addressing to point -// to its function and optional LSDA. -// __register_frame() has existed in all versions of Mac OS X, but in 10.4 and -// 10.5 it was buggy and did not actually register the FDE with the unwinder. -// In 10.6 and later it does register properly. -extern void __register_frame(const void *fde); -extern void __deregister_frame(const void *fde); - -// _Unwind_Find_FDE() will locate the FDE if the pc is in some function that has -// an associated FDE. Note, Mac OS X 10.6 and later, introduces "compact unwind -// info" which the runtime uses in preference to DWARF unwind info. This -// function will only work if the target function has an FDE but no compact -// unwind info. -struct dwarf_eh_bases { - uintptr_t tbase; - uintptr_t dbase; - uintptr_t func; -}; -extern const void *_Unwind_Find_FDE(const void *pc, struct dwarf_eh_bases *); - - -// This function attempts to find the start (address of first instruction) of -// a function given an address inside the function. It only works if the -// function has an FDE (DWARF unwind info). -// This function is unimplemented on Mac OS X 10.6 and later. Instead, use -// _Unwind_Find_FDE() and look at the dwarf_eh_bases.func result. -extern void *_Unwind_FindEnclosingFunction(void *pc); - -// Mac OS X does not support text-rel and data-rel addressing so these functions -// are unimplemented -extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context) - LIBUNWIND_UNAVAIL; -extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context) - LIBUNWIND_UNAVAIL; - -// Mac OS X 10.4 and 10.5 had implementations of these functions in -// libgcc_s.dylib, but they never worked. -/// These functions are no longer available on Mac OS X. -extern void __register_frame_info_bases(const void *fde, void *ob, void *tb, - void *db) LIBUNWIND_UNAVAIL; -extern void __register_frame_info(const void *fde, void *ob) - LIBUNWIND_UNAVAIL; -extern void __register_frame_info_table_bases(const void *fde, void *ob, - void *tb, void *db) - LIBUNWIND_UNAVAIL; -extern void __register_frame_info_table(const void *fde, void *ob) - LIBUNWIND_UNAVAIL; -extern void __register_frame_table(const void *fde) - LIBUNWIND_UNAVAIL; -extern void *__deregister_frame_info(const void *fde) - LIBUNWIND_UNAVAIL; -extern void *__deregister_frame_info_bases(const void *fde) - LIBUNWIND_UNAVAIL; - -#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) -#ifndef _WIN32 -typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD; -typedef struct _CONTEXT CONTEXT; -typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT; -#elif !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000 -typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT; -#endif -// This is the common wrapper for GCC-style personality functions with SEH. -extern EXCEPTION_DISPOSITION _GCC_specific_handler(EXCEPTION_RECORD *exc, - void *frame, - CONTEXT *ctx, - DISPATCHER_CONTEXT *disp, - __personality_routine pers); -#endif - -#ifdef __cplusplus -} -#endif - -#endif // __UNWIND_H__ Property changes on: head/contrib/llvm/projects/libunwind/include/unwind.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/include/libunwind.h =================================================================== --- head/contrib/llvm/projects/libunwind/include/libunwind.h (revision 345067) +++ head/contrib/llvm/projects/libunwind/include/libunwind.h (nonexistent) @@ -1,933 +0,0 @@ -//===---------------------------- libunwind.h -----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Compatible with libunwind API documented at: -// http://www.nongnu.org/libunwind/man/libunwind(3).html -// -//===----------------------------------------------------------------------===// - -#ifndef __LIBUNWIND__ -#define __LIBUNWIND__ - -#include <__libunwind_config.h> - -#include -#include - -#ifdef __APPLE__ - #if __clang__ - #if __has_include() - #include - #endif - #elif __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 - #include - #endif - - #ifdef __arm__ - #define LIBUNWIND_AVAIL __attribute__((unavailable)) - #elif defined(__OSX_AVAILABLE_STARTING) - #define LIBUNWIND_AVAIL __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0) - #else - #include - #ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER - #define LIBUNWIND_AVAIL AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER - #else - #define LIBUNWIND_AVAIL __attribute__((unavailable)) - #endif - #endif -#else - #define LIBUNWIND_AVAIL -#endif - -/* error codes */ -enum { - UNW_ESUCCESS = 0, /* no error */ - UNW_EUNSPEC = -6540, /* unspecified (general) error */ - UNW_ENOMEM = -6541, /* out of memory */ - UNW_EBADREG = -6542, /* bad register number */ - UNW_EREADONLYREG = -6543, /* attempt to write read-only register */ - UNW_ESTOPUNWIND = -6544, /* stop unwinding */ - UNW_EINVALIDIP = -6545, /* invalid IP */ - UNW_EBADFRAME = -6546, /* bad frame */ - UNW_EINVAL = -6547, /* unsupported operation or bad value */ - UNW_EBADVERSION = -6548, /* unwind info has unsupported version */ - UNW_ENOINFO = -6549 /* no unwind info found */ -#if defined(_LIBUNWIND_TARGET_AARCH64) && !defined(_LIBUNWIND_IS_NATIVE_ONLY) - , UNW_ECROSSRASIGNING = -6550 /* cross unwind with return address signing */ -#endif -}; - -struct unw_context_t { - uint64_t data[_LIBUNWIND_CONTEXT_SIZE]; -}; -typedef struct unw_context_t unw_context_t; - -struct unw_cursor_t { - uint64_t data[_LIBUNWIND_CURSOR_SIZE]; -}; -typedef struct unw_cursor_t unw_cursor_t; - -typedef struct unw_addr_space *unw_addr_space_t; - -typedef int unw_regnum_t; -typedef uintptr_t unw_word_t; -#if defined(__arm__) -typedef uint64_t unw_fpreg_t; -#else -typedef double unw_fpreg_t; -#endif - -struct unw_proc_info_t { - unw_word_t start_ip; /* start address of function */ - unw_word_t end_ip; /* address after end of function */ - unw_word_t lsda; /* address of language specific data area, */ - /* or zero if not used */ - unw_word_t handler; /* personality routine, or zero if not used */ - unw_word_t gp; /* not used */ - unw_word_t flags; /* not used */ - uint32_t format; /* compact unwind encoding, or zero if none */ - uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */ - unw_word_t unwind_info; /* address of DWARF unwind info, or zero */ - unw_word_t extra; /* mach_header of mach-o image containing func */ -}; -typedef struct unw_proc_info_t unw_proc_info_t; - -#ifdef __cplusplus -extern "C" { -#endif - -extern int unw_getcontext(unw_context_t *) LIBUNWIND_AVAIL; -extern int unw_init_local(unw_cursor_t *, unw_context_t *) LIBUNWIND_AVAIL; -extern int unw_step(unw_cursor_t *) LIBUNWIND_AVAIL; -extern int unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *) LIBUNWIND_AVAIL; -extern int unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *) LIBUNWIND_AVAIL; -extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t) LIBUNWIND_AVAIL; -extern int unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t) LIBUNWIND_AVAIL; -extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL; - -#ifdef __arm__ -/* Save VFP registers in FSTMX format (instead of FSTMD). */ -extern void unw_save_vfp_as_X(unw_cursor_t *) LIBUNWIND_AVAIL; -#endif - - -extern const char *unw_regname(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL; -extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL; -extern int unw_is_fpreg(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL; -extern int unw_is_signal_frame(unw_cursor_t *) LIBUNWIND_AVAIL; -extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUNWIND_AVAIL; -//extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*); - -extern unw_addr_space_t unw_local_addr_space; - -#ifdef UNW_REMOTE -/* - * Mac OS X "remote" API for unwinding other processes on same machine - * - */ -extern unw_addr_space_t unw_create_addr_space_for_task(task_t); -extern void unw_destroy_addr_space(unw_addr_space_t); -extern int unw_init_remote_thread(unw_cursor_t *, unw_addr_space_t, thread_t *); -#endif /* UNW_REMOTE */ - -/* - * traditional libunwind "remote" API - * NOT IMPLEMENTED on Mac OS X - * - * extern int unw_init_remote(unw_cursor_t*, unw_addr_space_t, - * thread_t*); - * extern unw_accessors_t unw_get_accessors(unw_addr_space_t); - * extern unw_addr_space_t unw_create_addr_space(unw_accessors_t, int); - * extern void unw_flush_cache(unw_addr_space_t, unw_word_t, - * unw_word_t); - * extern int unw_set_caching_policy(unw_addr_space_t, - * unw_caching_policy_t); - * extern void _U_dyn_register(unw_dyn_info_t*); - * extern void _U_dyn_cancel(unw_dyn_info_t*); - */ - -#ifdef __cplusplus -} -#endif - -// architecture independent register numbers -enum { - UNW_REG_IP = -1, // instruction pointer - UNW_REG_SP = -2, // stack pointer -}; - -// 32-bit x86 registers -enum { - UNW_X86_EAX = 0, - UNW_X86_ECX = 1, - UNW_X86_EDX = 2, - UNW_X86_EBX = 3, - UNW_X86_EBP = 4, - UNW_X86_ESP = 5, - UNW_X86_ESI = 6, - UNW_X86_EDI = 7 -}; - -// 64-bit x86_64 registers -enum { - UNW_X86_64_RAX = 0, - UNW_X86_64_RDX = 1, - UNW_X86_64_RCX = 2, - UNW_X86_64_RBX = 3, - UNW_X86_64_RSI = 4, - UNW_X86_64_RDI = 5, - UNW_X86_64_RBP = 6, - UNW_X86_64_RSP = 7, - UNW_X86_64_R8 = 8, - UNW_X86_64_R9 = 9, - UNW_X86_64_R10 = 10, - UNW_X86_64_R11 = 11, - UNW_X86_64_R12 = 12, - UNW_X86_64_R13 = 13, - UNW_X86_64_R14 = 14, - UNW_X86_64_R15 = 15, - UNW_X86_64_RIP = 16, - UNW_X86_64_XMM0 = 17, - UNW_X86_64_XMM1 = 18, - UNW_X86_64_XMM2 = 19, - UNW_X86_64_XMM3 = 20, - UNW_X86_64_XMM4 = 21, - UNW_X86_64_XMM5 = 22, - UNW_X86_64_XMM6 = 23, - UNW_X86_64_XMM7 = 24, - UNW_X86_64_XMM8 = 25, - UNW_X86_64_XMM9 = 26, - UNW_X86_64_XMM10 = 27, - UNW_X86_64_XMM11 = 28, - UNW_X86_64_XMM12 = 29, - UNW_X86_64_XMM13 = 30, - UNW_X86_64_XMM14 = 31, - UNW_X86_64_XMM15 = 32, -}; - - -// 32-bit ppc register numbers -enum { - UNW_PPC_R0 = 0, - UNW_PPC_R1 = 1, - UNW_PPC_R2 = 2, - UNW_PPC_R3 = 3, - UNW_PPC_R4 = 4, - UNW_PPC_R5 = 5, - UNW_PPC_R6 = 6, - UNW_PPC_R7 = 7, - UNW_PPC_R8 = 8, - UNW_PPC_R9 = 9, - UNW_PPC_R10 = 10, - UNW_PPC_R11 = 11, - UNW_PPC_R12 = 12, - UNW_PPC_R13 = 13, - UNW_PPC_R14 = 14, - UNW_PPC_R15 = 15, - UNW_PPC_R16 = 16, - UNW_PPC_R17 = 17, - UNW_PPC_R18 = 18, - UNW_PPC_R19 = 19, - UNW_PPC_R20 = 20, - UNW_PPC_R21 = 21, - UNW_PPC_R22 = 22, - UNW_PPC_R23 = 23, - UNW_PPC_R24 = 24, - UNW_PPC_R25 = 25, - UNW_PPC_R26 = 26, - UNW_PPC_R27 = 27, - UNW_PPC_R28 = 28, - UNW_PPC_R29 = 29, - UNW_PPC_R30 = 30, - UNW_PPC_R31 = 31, - UNW_PPC_F0 = 32, - UNW_PPC_F1 = 33, - UNW_PPC_F2 = 34, - UNW_PPC_F3 = 35, - UNW_PPC_F4 = 36, - UNW_PPC_F5 = 37, - UNW_PPC_F6 = 38, - UNW_PPC_F7 = 39, - UNW_PPC_F8 = 40, - UNW_PPC_F9 = 41, - UNW_PPC_F10 = 42, - UNW_PPC_F11 = 43, - UNW_PPC_F12 = 44, - UNW_PPC_F13 = 45, - UNW_PPC_F14 = 46, - UNW_PPC_F15 = 47, - UNW_PPC_F16 = 48, - UNW_PPC_F17 = 49, - UNW_PPC_F18 = 50, - UNW_PPC_F19 = 51, - UNW_PPC_F20 = 52, - UNW_PPC_F21 = 53, - UNW_PPC_F22 = 54, - UNW_PPC_F23 = 55, - UNW_PPC_F24 = 56, - UNW_PPC_F25 = 57, - UNW_PPC_F26 = 58, - UNW_PPC_F27 = 59, - UNW_PPC_F28 = 60, - UNW_PPC_F29 = 61, - UNW_PPC_F30 = 62, - UNW_PPC_F31 = 63, - UNW_PPC_MQ = 64, - UNW_PPC_LR = 65, - UNW_PPC_CTR = 66, - UNW_PPC_AP = 67, - UNW_PPC_CR0 = 68, - UNW_PPC_CR1 = 69, - UNW_PPC_CR2 = 70, - UNW_PPC_CR3 = 71, - UNW_PPC_CR4 = 72, - UNW_PPC_CR5 = 73, - UNW_PPC_CR6 = 74, - UNW_PPC_CR7 = 75, - UNW_PPC_XER = 76, - UNW_PPC_V0 = 77, - UNW_PPC_V1 = 78, - UNW_PPC_V2 = 79, - UNW_PPC_V3 = 80, - UNW_PPC_V4 = 81, - UNW_PPC_V5 = 82, - UNW_PPC_V6 = 83, - UNW_PPC_V7 = 84, - UNW_PPC_V8 = 85, - UNW_PPC_V9 = 86, - UNW_PPC_V10 = 87, - UNW_PPC_V11 = 88, - UNW_PPC_V12 = 89, - UNW_PPC_V13 = 90, - UNW_PPC_V14 = 91, - UNW_PPC_V15 = 92, - UNW_PPC_V16 = 93, - UNW_PPC_V17 = 94, - UNW_PPC_V18 = 95, - UNW_PPC_V19 = 96, - UNW_PPC_V20 = 97, - UNW_PPC_V21 = 98, - UNW_PPC_V22 = 99, - UNW_PPC_V23 = 100, - UNW_PPC_V24 = 101, - UNW_PPC_V25 = 102, - UNW_PPC_V26 = 103, - UNW_PPC_V27 = 104, - UNW_PPC_V28 = 105, - UNW_PPC_V29 = 106, - UNW_PPC_V30 = 107, - UNW_PPC_V31 = 108, - UNW_PPC_VRSAVE = 109, - UNW_PPC_VSCR = 110, - UNW_PPC_SPE_ACC = 111, - UNW_PPC_SPEFSCR = 112 -}; - -// 64-bit ppc register numbers -enum { - UNW_PPC64_R0 = 0, - UNW_PPC64_R1 = 1, - UNW_PPC64_R2 = 2, - UNW_PPC64_R3 = 3, - UNW_PPC64_R4 = 4, - UNW_PPC64_R5 = 5, - UNW_PPC64_R6 = 6, - UNW_PPC64_R7 = 7, - UNW_PPC64_R8 = 8, - UNW_PPC64_R9 = 9, - UNW_PPC64_R10 = 10, - UNW_PPC64_R11 = 11, - UNW_PPC64_R12 = 12, - UNW_PPC64_R13 = 13, - UNW_PPC64_R14 = 14, - UNW_PPC64_R15 = 15, - UNW_PPC64_R16 = 16, - UNW_PPC64_R17 = 17, - UNW_PPC64_R18 = 18, - UNW_PPC64_R19 = 19, - UNW_PPC64_R20 = 20, - UNW_PPC64_R21 = 21, - UNW_PPC64_R22 = 22, - UNW_PPC64_R23 = 23, - UNW_PPC64_R24 = 24, - UNW_PPC64_R25 = 25, - UNW_PPC64_R26 = 26, - UNW_PPC64_R27 = 27, - UNW_PPC64_R28 = 28, - UNW_PPC64_R29 = 29, - UNW_PPC64_R30 = 30, - UNW_PPC64_R31 = 31, - UNW_PPC64_F0 = 32, - UNW_PPC64_F1 = 33, - UNW_PPC64_F2 = 34, - UNW_PPC64_F3 = 35, - UNW_PPC64_F4 = 36, - UNW_PPC64_F5 = 37, - UNW_PPC64_F6 = 38, - UNW_PPC64_F7 = 39, - UNW_PPC64_F8 = 40, - UNW_PPC64_F9 = 41, - UNW_PPC64_F10 = 42, - UNW_PPC64_F11 = 43, - UNW_PPC64_F12 = 44, - UNW_PPC64_F13 = 45, - UNW_PPC64_F14 = 46, - UNW_PPC64_F15 = 47, - UNW_PPC64_F16 = 48, - UNW_PPC64_F17 = 49, - UNW_PPC64_F18 = 50, - UNW_PPC64_F19 = 51, - UNW_PPC64_F20 = 52, - UNW_PPC64_F21 = 53, - UNW_PPC64_F22 = 54, - UNW_PPC64_F23 = 55, - UNW_PPC64_F24 = 56, - UNW_PPC64_F25 = 57, - UNW_PPC64_F26 = 58, - UNW_PPC64_F27 = 59, - UNW_PPC64_F28 = 60, - UNW_PPC64_F29 = 61, - UNW_PPC64_F30 = 62, - UNW_PPC64_F31 = 63, - // 64: reserved - UNW_PPC64_LR = 65, - UNW_PPC64_CTR = 66, - // 67: reserved - UNW_PPC64_CR0 = 68, - UNW_PPC64_CR1 = 69, - UNW_PPC64_CR2 = 70, - UNW_PPC64_CR3 = 71, - UNW_PPC64_CR4 = 72, - UNW_PPC64_CR5 = 73, - UNW_PPC64_CR6 = 74, - UNW_PPC64_CR7 = 75, - UNW_PPC64_XER = 76, - UNW_PPC64_V0 = 77, - UNW_PPC64_V1 = 78, - UNW_PPC64_V2 = 79, - UNW_PPC64_V3 = 80, - UNW_PPC64_V4 = 81, - UNW_PPC64_V5 = 82, - UNW_PPC64_V6 = 83, - UNW_PPC64_V7 = 84, - UNW_PPC64_V8 = 85, - UNW_PPC64_V9 = 86, - UNW_PPC64_V10 = 87, - UNW_PPC64_V11 = 88, - UNW_PPC64_V12 = 89, - UNW_PPC64_V13 = 90, - UNW_PPC64_V14 = 91, - UNW_PPC64_V15 = 92, - UNW_PPC64_V16 = 93, - UNW_PPC64_V17 = 94, - UNW_PPC64_V18 = 95, - UNW_PPC64_V19 = 96, - UNW_PPC64_V20 = 97, - UNW_PPC64_V21 = 98, - UNW_PPC64_V22 = 99, - UNW_PPC64_V23 = 100, - UNW_PPC64_V24 = 101, - UNW_PPC64_V25 = 102, - UNW_PPC64_V26 = 103, - UNW_PPC64_V27 = 104, - UNW_PPC64_V28 = 105, - UNW_PPC64_V29 = 106, - UNW_PPC64_V30 = 107, - UNW_PPC64_V31 = 108, - // 109, 111-113: OpenPOWER ELF V2 ABI: reserved - // Borrowing VRSAVE number from PPC32. - UNW_PPC64_VRSAVE = 109, - UNW_PPC64_VSCR = 110, - UNW_PPC64_TFHAR = 114, - UNW_PPC64_TFIAR = 115, - UNW_PPC64_TEXASR = 116, - UNW_PPC64_VS0 = UNW_PPC64_F0, - UNW_PPC64_VS1 = UNW_PPC64_F1, - UNW_PPC64_VS2 = UNW_PPC64_F2, - UNW_PPC64_VS3 = UNW_PPC64_F3, - UNW_PPC64_VS4 = UNW_PPC64_F4, - UNW_PPC64_VS5 = UNW_PPC64_F5, - UNW_PPC64_VS6 = UNW_PPC64_F6, - UNW_PPC64_VS7 = UNW_PPC64_F7, - UNW_PPC64_VS8 = UNW_PPC64_F8, - UNW_PPC64_VS9 = UNW_PPC64_F9, - UNW_PPC64_VS10 = UNW_PPC64_F10, - UNW_PPC64_VS11 = UNW_PPC64_F11, - UNW_PPC64_VS12 = UNW_PPC64_F12, - UNW_PPC64_VS13 = UNW_PPC64_F13, - UNW_PPC64_VS14 = UNW_PPC64_F14, - UNW_PPC64_VS15 = UNW_PPC64_F15, - UNW_PPC64_VS16 = UNW_PPC64_F16, - UNW_PPC64_VS17 = UNW_PPC64_F17, - UNW_PPC64_VS18 = UNW_PPC64_F18, - UNW_PPC64_VS19 = UNW_PPC64_F19, - UNW_PPC64_VS20 = UNW_PPC64_F20, - UNW_PPC64_VS21 = UNW_PPC64_F21, - UNW_PPC64_VS22 = UNW_PPC64_F22, - UNW_PPC64_VS23 = UNW_PPC64_F23, - UNW_PPC64_VS24 = UNW_PPC64_F24, - UNW_PPC64_VS25 = UNW_PPC64_F25, - UNW_PPC64_VS26 = UNW_PPC64_F26, - UNW_PPC64_VS27 = UNW_PPC64_F27, - UNW_PPC64_VS28 = UNW_PPC64_F28, - UNW_PPC64_VS29 = UNW_PPC64_F29, - UNW_PPC64_VS30 = UNW_PPC64_F30, - UNW_PPC64_VS31 = UNW_PPC64_F31, - UNW_PPC64_VS32 = UNW_PPC64_V0, - UNW_PPC64_VS33 = UNW_PPC64_V1, - UNW_PPC64_VS34 = UNW_PPC64_V2, - UNW_PPC64_VS35 = UNW_PPC64_V3, - UNW_PPC64_VS36 = UNW_PPC64_V4, - UNW_PPC64_VS37 = UNW_PPC64_V5, - UNW_PPC64_VS38 = UNW_PPC64_V6, - UNW_PPC64_VS39 = UNW_PPC64_V7, - UNW_PPC64_VS40 = UNW_PPC64_V8, - UNW_PPC64_VS41 = UNW_PPC64_V9, - UNW_PPC64_VS42 = UNW_PPC64_V10, - UNW_PPC64_VS43 = UNW_PPC64_V11, - UNW_PPC64_VS44 = UNW_PPC64_V12, - UNW_PPC64_VS45 = UNW_PPC64_V13, - UNW_PPC64_VS46 = UNW_PPC64_V14, - UNW_PPC64_VS47 = UNW_PPC64_V15, - UNW_PPC64_VS48 = UNW_PPC64_V16, - UNW_PPC64_VS49 = UNW_PPC64_V17, - UNW_PPC64_VS50 = UNW_PPC64_V18, - UNW_PPC64_VS51 = UNW_PPC64_V19, - UNW_PPC64_VS52 = UNW_PPC64_V20, - UNW_PPC64_VS53 = UNW_PPC64_V21, - UNW_PPC64_VS54 = UNW_PPC64_V22, - UNW_PPC64_VS55 = UNW_PPC64_V23, - UNW_PPC64_VS56 = UNW_PPC64_V24, - UNW_PPC64_VS57 = UNW_PPC64_V25, - UNW_PPC64_VS58 = UNW_PPC64_V26, - UNW_PPC64_VS59 = UNW_PPC64_V27, - UNW_PPC64_VS60 = UNW_PPC64_V28, - UNW_PPC64_VS61 = UNW_PPC64_V29, - UNW_PPC64_VS62 = UNW_PPC64_V30, - UNW_PPC64_VS63 = UNW_PPC64_V31 -}; - -// 64-bit ARM64 registers -enum { - UNW_ARM64_X0 = 0, - UNW_ARM64_X1 = 1, - UNW_ARM64_X2 = 2, - UNW_ARM64_X3 = 3, - UNW_ARM64_X4 = 4, - UNW_ARM64_X5 = 5, - UNW_ARM64_X6 = 6, - UNW_ARM64_X7 = 7, - UNW_ARM64_X8 = 8, - UNW_ARM64_X9 = 9, - UNW_ARM64_X10 = 10, - UNW_ARM64_X11 = 11, - UNW_ARM64_X12 = 12, - UNW_ARM64_X13 = 13, - UNW_ARM64_X14 = 14, - UNW_ARM64_X15 = 15, - UNW_ARM64_X16 = 16, - UNW_ARM64_X17 = 17, - UNW_ARM64_X18 = 18, - UNW_ARM64_X19 = 19, - UNW_ARM64_X20 = 20, - UNW_ARM64_X21 = 21, - UNW_ARM64_X22 = 22, - UNW_ARM64_X23 = 23, - UNW_ARM64_X24 = 24, - UNW_ARM64_X25 = 25, - UNW_ARM64_X26 = 26, - UNW_ARM64_X27 = 27, - UNW_ARM64_X28 = 28, - UNW_ARM64_X29 = 29, - UNW_ARM64_FP = 29, - UNW_ARM64_X30 = 30, - UNW_ARM64_LR = 30, - UNW_ARM64_X31 = 31, - UNW_ARM64_SP = 31, - // reserved block - UNW_ARM64_RA_SIGN_STATE = 34, - // reserved block - UNW_ARM64_D0 = 64, - UNW_ARM64_D1 = 65, - UNW_ARM64_D2 = 66, - UNW_ARM64_D3 = 67, - UNW_ARM64_D4 = 68, - UNW_ARM64_D5 = 69, - UNW_ARM64_D6 = 70, - UNW_ARM64_D7 = 71, - UNW_ARM64_D8 = 72, - UNW_ARM64_D9 = 73, - UNW_ARM64_D10 = 74, - UNW_ARM64_D11 = 75, - UNW_ARM64_D12 = 76, - UNW_ARM64_D13 = 77, - UNW_ARM64_D14 = 78, - UNW_ARM64_D15 = 79, - UNW_ARM64_D16 = 80, - UNW_ARM64_D17 = 81, - UNW_ARM64_D18 = 82, - UNW_ARM64_D19 = 83, - UNW_ARM64_D20 = 84, - UNW_ARM64_D21 = 85, - UNW_ARM64_D22 = 86, - UNW_ARM64_D23 = 87, - UNW_ARM64_D24 = 88, - UNW_ARM64_D25 = 89, - UNW_ARM64_D26 = 90, - UNW_ARM64_D27 = 91, - UNW_ARM64_D28 = 92, - UNW_ARM64_D29 = 93, - UNW_ARM64_D30 = 94, - UNW_ARM64_D31 = 95, -}; - -// 32-bit ARM registers. Numbers match DWARF for ARM spec #3.1 Table 1. -// Naming scheme uses recommendations given in Note 4 for VFP-v2 and VFP-v3. -// In this scheme, even though the 64-bit floating point registers D0-D31 -// overlap physically with the 32-bit floating pointer registers S0-S31, -// they are given a non-overlapping range of register numbers. -// -// Commented out ranges are not preserved during unwinding. -enum { - UNW_ARM_R0 = 0, - UNW_ARM_R1 = 1, - UNW_ARM_R2 = 2, - UNW_ARM_R3 = 3, - UNW_ARM_R4 = 4, - UNW_ARM_R5 = 5, - UNW_ARM_R6 = 6, - UNW_ARM_R7 = 7, - UNW_ARM_R8 = 8, - UNW_ARM_R9 = 9, - UNW_ARM_R10 = 10, - UNW_ARM_R11 = 11, - UNW_ARM_R12 = 12, - UNW_ARM_SP = 13, // Logical alias for UNW_REG_SP - UNW_ARM_R13 = 13, - UNW_ARM_LR = 14, - UNW_ARM_R14 = 14, - UNW_ARM_IP = 15, // Logical alias for UNW_REG_IP - UNW_ARM_R15 = 15, - // 16-63 -- OBSOLETE. Used in VFP1 to represent both S0-S31 and D0-D31. - UNW_ARM_S0 = 64, - UNW_ARM_S1 = 65, - UNW_ARM_S2 = 66, - UNW_ARM_S3 = 67, - UNW_ARM_S4 = 68, - UNW_ARM_S5 = 69, - UNW_ARM_S6 = 70, - UNW_ARM_S7 = 71, - UNW_ARM_S8 = 72, - UNW_ARM_S9 = 73, - UNW_ARM_S10 = 74, - UNW_ARM_S11 = 75, - UNW_ARM_S12 = 76, - UNW_ARM_S13 = 77, - UNW_ARM_S14 = 78, - UNW_ARM_S15 = 79, - UNW_ARM_S16 = 80, - UNW_ARM_S17 = 81, - UNW_ARM_S18 = 82, - UNW_ARM_S19 = 83, - UNW_ARM_S20 = 84, - UNW_ARM_S21 = 85, - UNW_ARM_S22 = 86, - UNW_ARM_S23 = 87, - UNW_ARM_S24 = 88, - UNW_ARM_S25 = 89, - UNW_ARM_S26 = 90, - UNW_ARM_S27 = 91, - UNW_ARM_S28 = 92, - UNW_ARM_S29 = 93, - UNW_ARM_S30 = 94, - UNW_ARM_S31 = 95, - // 96-103 -- OBSOLETE. F0-F7. Used by the FPA system. Superseded by VFP. - // 104-111 -- wCGR0-wCGR7, ACC0-ACC7 (Intel wireless MMX) - UNW_ARM_WR0 = 112, - UNW_ARM_WR1 = 113, - UNW_ARM_WR2 = 114, - UNW_ARM_WR3 = 115, - UNW_ARM_WR4 = 116, - UNW_ARM_WR5 = 117, - UNW_ARM_WR6 = 118, - UNW_ARM_WR7 = 119, - UNW_ARM_WR8 = 120, - UNW_ARM_WR9 = 121, - UNW_ARM_WR10 = 122, - UNW_ARM_WR11 = 123, - UNW_ARM_WR12 = 124, - UNW_ARM_WR13 = 125, - UNW_ARM_WR14 = 126, - UNW_ARM_WR15 = 127, - // 128-133 -- SPSR, SPSR_{FIQ|IRQ|ABT|UND|SVC} - // 134-143 -- Reserved - // 144-150 -- R8_USR-R14_USR - // 151-157 -- R8_FIQ-R14_FIQ - // 158-159 -- R13_IRQ-R14_IRQ - // 160-161 -- R13_ABT-R14_ABT - // 162-163 -- R13_UND-R14_UND - // 164-165 -- R13_SVC-R14_SVC - // 166-191 -- Reserved - UNW_ARM_WC0 = 192, - UNW_ARM_WC1 = 193, - UNW_ARM_WC2 = 194, - UNW_ARM_WC3 = 195, - // 196-199 -- wC4-wC7 (Intel wireless MMX control) - // 200-255 -- Reserved - UNW_ARM_D0 = 256, - UNW_ARM_D1 = 257, - UNW_ARM_D2 = 258, - UNW_ARM_D3 = 259, - UNW_ARM_D4 = 260, - UNW_ARM_D5 = 261, - UNW_ARM_D6 = 262, - UNW_ARM_D7 = 263, - UNW_ARM_D8 = 264, - UNW_ARM_D9 = 265, - UNW_ARM_D10 = 266, - UNW_ARM_D11 = 267, - UNW_ARM_D12 = 268, - UNW_ARM_D13 = 269, - UNW_ARM_D14 = 270, - UNW_ARM_D15 = 271, - UNW_ARM_D16 = 272, - UNW_ARM_D17 = 273, - UNW_ARM_D18 = 274, - UNW_ARM_D19 = 275, - UNW_ARM_D20 = 276, - UNW_ARM_D21 = 277, - UNW_ARM_D22 = 278, - UNW_ARM_D23 = 279, - UNW_ARM_D24 = 280, - UNW_ARM_D25 = 281, - UNW_ARM_D26 = 282, - UNW_ARM_D27 = 283, - UNW_ARM_D28 = 284, - UNW_ARM_D29 = 285, - UNW_ARM_D30 = 286, - UNW_ARM_D31 = 287, - // 288-319 -- Reserved for VFP/Neon - // 320-8191 -- Reserved - // 8192-16383 -- Unspecified vendor co-processor register. -}; - -// OpenRISC1000 register numbers -enum { - UNW_OR1K_R0 = 0, - UNW_OR1K_R1 = 1, - UNW_OR1K_R2 = 2, - UNW_OR1K_R3 = 3, - UNW_OR1K_R4 = 4, - UNW_OR1K_R5 = 5, - UNW_OR1K_R6 = 6, - UNW_OR1K_R7 = 7, - UNW_OR1K_R8 = 8, - UNW_OR1K_R9 = 9, - UNW_OR1K_R10 = 10, - UNW_OR1K_R11 = 11, - UNW_OR1K_R12 = 12, - UNW_OR1K_R13 = 13, - UNW_OR1K_R14 = 14, - UNW_OR1K_R15 = 15, - UNW_OR1K_R16 = 16, - UNW_OR1K_R17 = 17, - UNW_OR1K_R18 = 18, - UNW_OR1K_R19 = 19, - UNW_OR1K_R20 = 20, - UNW_OR1K_R21 = 21, - UNW_OR1K_R22 = 22, - UNW_OR1K_R23 = 23, - UNW_OR1K_R24 = 24, - UNW_OR1K_R25 = 25, - UNW_OR1K_R26 = 26, - UNW_OR1K_R27 = 27, - UNW_OR1K_R28 = 28, - UNW_OR1K_R29 = 29, - UNW_OR1K_R30 = 30, - UNW_OR1K_R31 = 31, - UNW_OR1K_EPCR = 32, -}; - -// 64-bit RISC-V registers -enum { - UNW_RISCV_X0 = 0, - UNW_RISCV_X1 = 1, - UNW_RISCV_RA = 1, - UNW_RISCV_X2 = 2, - UNW_RISCV_SP = 2, - UNW_RISCV_X3 = 3, - UNW_RISCV_X4 = 4, - UNW_RISCV_X5 = 5, - UNW_RISCV_X6 = 6, - UNW_RISCV_X7 = 7, - UNW_RISCV_X8 = 8, - UNW_RISCV_X9 = 9, - UNW_RISCV_X10 = 10, - UNW_RISCV_X11 = 11, - UNW_RISCV_X12 = 12, - UNW_RISCV_X13 = 13, - UNW_RISCV_X14 = 14, - UNW_RISCV_X15 = 15, - UNW_RISCV_X16 = 16, - UNW_RISCV_X17 = 17, - UNW_RISCV_X18 = 18, - UNW_RISCV_X19 = 19, - UNW_RISCV_X20 = 20, - UNW_RISCV_X21 = 21, - UNW_RISCV_X22 = 22, - UNW_RISCV_X23 = 23, - UNW_RISCV_X24 = 24, - UNW_RISCV_X25 = 25, - UNW_RISCV_X26 = 26, - UNW_RISCV_X27 = 27, - UNW_RISCV_X28 = 28, - UNW_RISCV_X29 = 29, - UNW_RISCV_X30 = 30, - UNW_RISCV_X31 = 31, - // reserved block - UNW_RISCV_D0 = 64, - UNW_RISCV_D1 = 65, - UNW_RISCV_D2 = 66, - UNW_RISCV_D3 = 67, - UNW_RISCV_D4 = 68, - UNW_RISCV_D5 = 69, - UNW_RISCV_D6 = 70, - UNW_RISCV_D7 = 71, - UNW_RISCV_D8 = 72, - UNW_RISCV_D9 = 73, - UNW_RISCV_D10 = 74, - UNW_RISCV_D11 = 75, - UNW_RISCV_D12 = 76, - UNW_RISCV_D13 = 77, - UNW_RISCV_D14 = 78, - UNW_RISCV_D15 = 79, - UNW_RISCV_D16 = 80, - UNW_RISCV_D17 = 81, - UNW_RISCV_D18 = 82, - UNW_RISCV_D19 = 83, - UNW_RISCV_D20 = 84, - UNW_RISCV_D21 = 85, - UNW_RISCV_D22 = 86, - UNW_RISCV_D23 = 87, - UNW_RISCV_D24 = 88, - UNW_RISCV_D25 = 89, - UNW_RISCV_D26 = 90, - UNW_RISCV_D27 = 91, - UNW_RISCV_D28 = 92, - UNW_RISCV_D29 = 93, - UNW_RISCV_D30 = 94, - UNW_RISCV_D31 = 95, -}; - -// MIPS registers -enum { - UNW_MIPS_R0 = 0, - UNW_MIPS_R1 = 1, - UNW_MIPS_R2 = 2, - UNW_MIPS_R3 = 3, - UNW_MIPS_R4 = 4, - UNW_MIPS_R5 = 5, - UNW_MIPS_R6 = 6, - UNW_MIPS_R7 = 7, - UNW_MIPS_R8 = 8, - UNW_MIPS_R9 = 9, - UNW_MIPS_R10 = 10, - UNW_MIPS_R11 = 11, - UNW_MIPS_R12 = 12, - UNW_MIPS_R13 = 13, - UNW_MIPS_R14 = 14, - UNW_MIPS_R15 = 15, - UNW_MIPS_R16 = 16, - UNW_MIPS_R17 = 17, - UNW_MIPS_R18 = 18, - UNW_MIPS_R19 = 19, - UNW_MIPS_R20 = 20, - UNW_MIPS_R21 = 21, - UNW_MIPS_R22 = 22, - UNW_MIPS_R23 = 23, - UNW_MIPS_R24 = 24, - UNW_MIPS_R25 = 25, - UNW_MIPS_R26 = 26, - UNW_MIPS_R27 = 27, - UNW_MIPS_R28 = 28, - UNW_MIPS_R29 = 29, - UNW_MIPS_R30 = 30, - UNW_MIPS_R31 = 31, - UNW_MIPS_F0 = 32, - UNW_MIPS_F1 = 33, - UNW_MIPS_F2 = 34, - UNW_MIPS_F3 = 35, - UNW_MIPS_F4 = 36, - UNW_MIPS_F5 = 37, - UNW_MIPS_F6 = 38, - UNW_MIPS_F7 = 39, - UNW_MIPS_F8 = 40, - UNW_MIPS_F9 = 41, - UNW_MIPS_F10 = 42, - UNW_MIPS_F11 = 43, - UNW_MIPS_F12 = 44, - UNW_MIPS_F13 = 45, - UNW_MIPS_F14 = 46, - UNW_MIPS_F15 = 47, - UNW_MIPS_F16 = 48, - UNW_MIPS_F17 = 49, - UNW_MIPS_F18 = 50, - UNW_MIPS_F19 = 51, - UNW_MIPS_F20 = 52, - UNW_MIPS_F21 = 53, - UNW_MIPS_F22 = 54, - UNW_MIPS_F23 = 55, - UNW_MIPS_F24 = 56, - UNW_MIPS_F25 = 57, - UNW_MIPS_F26 = 58, - UNW_MIPS_F27 = 59, - UNW_MIPS_F28 = 60, - UNW_MIPS_F29 = 61, - UNW_MIPS_F30 = 62, - UNW_MIPS_F31 = 63, - UNW_MIPS_HI = 64, - UNW_MIPS_LO = 65, -}; - -// SPARC registers -enum { - UNW_SPARC_G0 = 0, - UNW_SPARC_G1 = 1, - UNW_SPARC_G2 = 2, - UNW_SPARC_G3 = 3, - UNW_SPARC_G4 = 4, - UNW_SPARC_G5 = 5, - UNW_SPARC_G6 = 6, - UNW_SPARC_G7 = 7, - UNW_SPARC_O0 = 8, - UNW_SPARC_O1 = 9, - UNW_SPARC_O2 = 10, - UNW_SPARC_O3 = 11, - UNW_SPARC_O4 = 12, - UNW_SPARC_O5 = 13, - UNW_SPARC_O6 = 14, - UNW_SPARC_O7 = 15, - UNW_SPARC_L0 = 16, - UNW_SPARC_L1 = 17, - UNW_SPARC_L2 = 18, - UNW_SPARC_L3 = 19, - UNW_SPARC_L4 = 20, - UNW_SPARC_L5 = 21, - UNW_SPARC_L6 = 22, - UNW_SPARC_L7 = 23, - UNW_SPARC_I0 = 24, - UNW_SPARC_I1 = 25, - UNW_SPARC_I2 = 26, - UNW_SPARC_I3 = 27, - UNW_SPARC_I4 = 28, - UNW_SPARC_I5 = 29, - UNW_SPARC_I6 = 30, - UNW_SPARC_I7 = 31, -}; - -#endif Property changes on: head/contrib/llvm/projects/libunwind/include/libunwind.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/include/mach-o/compact_unwind_encoding.h =================================================================== --- head/contrib/llvm/projects/libunwind/include/mach-o/compact_unwind_encoding.h (revision 345067) +++ head/contrib/llvm/projects/libunwind/include/mach-o/compact_unwind_encoding.h (nonexistent) @@ -1,478 +0,0 @@ -//===------------------ mach-o/compact_unwind_encoding.h ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Darwin's alternative to DWARF based unwind encodings. -// -//===----------------------------------------------------------------------===// - - -#ifndef __COMPACT_UNWIND_ENCODING__ -#define __COMPACT_UNWIND_ENCODING__ - -#include - -// -// Compilers can emit standard DWARF FDEs in the __TEXT,__eh_frame section -// of object files. Or compilers can emit compact unwind information in -// the __LD,__compact_unwind section. -// -// When the linker creates a final linked image, it will create a -// __TEXT,__unwind_info section. This section is a small and fast way for the -// runtime to access unwind info for any given function. If the compiler -// emitted compact unwind info for the function, that compact unwind info will -// be encoded in the __TEXT,__unwind_info section. If the compiler emitted -// DWARF unwind info, the __TEXT,__unwind_info section will contain the offset -// of the FDE in the __TEXT,__eh_frame section in the final linked image. -// -// Note: Previously, the linker would transform some DWARF unwind infos into -// compact unwind info. But that is fragile and no longer done. - - -// -// The compact unwind endoding is a 32-bit value which encoded in an -// architecture specific way, which registers to restore from where, and how -// to unwind out of the function. -// -typedef uint32_t compact_unwind_encoding_t; - - -// architecture independent bits -enum { - UNWIND_IS_NOT_FUNCTION_START = 0x80000000, - UNWIND_HAS_LSDA = 0x40000000, - UNWIND_PERSONALITY_MASK = 0x30000000, -}; - - - - -// -// x86 -// -// 1-bit: start -// 1-bit: has lsda -// 2-bit: personality index -// -// 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=DWARF -// ebp based: -// 15-bits (5*3-bits per reg) register permutation -// 8-bits for stack offset -// frameless: -// 8-bits stack size -// 3-bits stack adjust -// 3-bits register count -// 10-bits register permutation -// -enum { - UNWIND_X86_MODE_MASK = 0x0F000000, - UNWIND_X86_MODE_EBP_FRAME = 0x01000000, - UNWIND_X86_MODE_STACK_IMMD = 0x02000000, - UNWIND_X86_MODE_STACK_IND = 0x03000000, - UNWIND_X86_MODE_DWARF = 0x04000000, - - UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF, - UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000, - - UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000, - UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000, - UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00, - UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, - - UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF, -}; - -enum { - UNWIND_X86_REG_NONE = 0, - UNWIND_X86_REG_EBX = 1, - UNWIND_X86_REG_ECX = 2, - UNWIND_X86_REG_EDX = 3, - UNWIND_X86_REG_EDI = 4, - UNWIND_X86_REG_ESI = 5, - UNWIND_X86_REG_EBP = 6, -}; - -// -// For x86 there are four modes for the compact unwind encoding: -// UNWIND_X86_MODE_EBP_FRAME: -// EBP based frame where EBP is push on stack immediately after return address, -// then ESP is moved to EBP. Thus, to unwind ESP is restored with the current -// EPB value, then EBP is restored by popping off the stack, and the return -// is done by popping the stack once more into the pc. -// All non-volatile registers that need to be restored must have been saved -// in a small range in the stack that starts EBP-4 to EBP-1020. The offset/4 -// is encoded in the UNWIND_X86_EBP_FRAME_OFFSET bits. The registers saved -// are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries. -// Each entry contains which register to restore. -// UNWIND_X86_MODE_STACK_IMMD: -// A "frameless" (EBP not used as frame pointer) function with a small -// constant stack size. To return, a constant (encoded in the compact -// unwind encoding) is added to the ESP. Then the return is done by -// popping the stack into the pc. -// All non-volatile registers that need to be restored must have been saved -// on the stack immediately after the return address. The stack_size/4 is -// encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024). -// The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT. -// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION constains which registers were -// saved and their order. -// UNWIND_X86_MODE_STACK_IND: -// A "frameless" (EBP not used as frame pointer) function large constant -// stack size. This case is like the previous, except the stack size is too -// large to encode in the compact unwind encoding. Instead it requires that -// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact -// encoding contains the offset to the nnnnnnnn value in the function in -// UNWIND_X86_FRAMELESS_STACK_SIZE. -// UNWIND_X86_MODE_DWARF: -// No compact unwind encoding is available. Instead the low 24-bits of the -// compact encoding is the offset of the DWARF FDE in the __eh_frame section. -// This mode is never used in object files. It is only generated by the -// linker in final linked images which have only DWARF unwind info for a -// function. -// -// The permutation encoding is a Lehmer code sequence encoded into a -// single variable-base number so we can encode the ordering of up to -// six registers in a 10-bit space. -// -// The following is the algorithm used to create the permutation encoding used -// with frameless stacks. It is passed the number of registers to be saved and -// an array of the register numbers saved. -// -//uint32_t permute_encode(uint32_t registerCount, const uint32_t registers[6]) -//{ -// uint32_t renumregs[6]; -// for (int i=6-registerCount; i < 6; ++i) { -// int countless = 0; -// for (int j=6-registerCount; j < i; ++j) { -// if ( registers[j] < registers[i] ) -// ++countless; -// } -// renumregs[i] = registers[i] - countless -1; -// } -// uint32_t permutationEncoding = 0; -// switch ( registerCount ) { -// case 6: -// permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] -// + 6*renumregs[2] + 2*renumregs[3] -// + renumregs[4]); -// break; -// case 5: -// permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] -// + 6*renumregs[3] + 2*renumregs[4] -// + renumregs[5]); -// break; -// case 4: -// permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] -// + 3*renumregs[4] + renumregs[5]); -// break; -// case 3: -// permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] -// + renumregs[5]); -// break; -// case 2: -// permutationEncoding |= (5*renumregs[4] + renumregs[5]); -// break; -// case 1: -// permutationEncoding |= (renumregs[5]); -// break; -// } -// return permutationEncoding; -//} -// - - - - -// -// x86_64 -// -// 1-bit: start -// 1-bit: has lsda -// 2-bit: personality index -// -// 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=DWARF -// rbp based: -// 15-bits (5*3-bits per reg) register permutation -// 8-bits for stack offset -// frameless: -// 8-bits stack size -// 3-bits stack adjust -// 3-bits register count -// 10-bits register permutation -// -enum { - UNWIND_X86_64_MODE_MASK = 0x0F000000, - UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, - UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000, - UNWIND_X86_64_MODE_STACK_IND = 0x03000000, - UNWIND_X86_64_MODE_DWARF = 0x04000000, - - UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF, - UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000, - - UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000, - UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000, - UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00, - UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, - - UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF, -}; - -enum { - UNWIND_X86_64_REG_NONE = 0, - UNWIND_X86_64_REG_RBX = 1, - UNWIND_X86_64_REG_R12 = 2, - UNWIND_X86_64_REG_R13 = 3, - UNWIND_X86_64_REG_R14 = 4, - UNWIND_X86_64_REG_R15 = 5, - UNWIND_X86_64_REG_RBP = 6, -}; -// -// For x86_64 there are four modes for the compact unwind encoding: -// UNWIND_X86_64_MODE_RBP_FRAME: -// RBP based frame where RBP is push on stack immediately after return address, -// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current -// EPB value, then RBP is restored by popping off the stack, and the return -// is done by popping the stack once more into the pc. -// All non-volatile registers that need to be restored must have been saved -// in a small range in the stack that starts RBP-8 to RBP-2040. The offset/8 -// is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits. The registers saved -// are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries. -// Each entry contains which register to restore. -// UNWIND_X86_64_MODE_STACK_IMMD: -// A "frameless" (RBP not used as frame pointer) function with a small -// constant stack size. To return, a constant (encoded in the compact -// unwind encoding) is added to the RSP. Then the return is done by -// popping the stack into the pc. -// All non-volatile registers that need to be restored must have been saved -// on the stack immediately after the return address. The stack_size/8 is -// encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048). -// The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT. -// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION constains which registers were -// saved and their order. -// UNWIND_X86_64_MODE_STACK_IND: -// A "frameless" (RBP not used as frame pointer) function large constant -// stack size. This case is like the previous, except the stack size is too -// large to encode in the compact unwind encoding. Instead it requires that -// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact -// encoding contains the offset to the nnnnnnnn value in the function in -// UNWIND_X86_64_FRAMELESS_STACK_SIZE. -// UNWIND_X86_64_MODE_DWARF: -// No compact unwind encoding is available. Instead the low 24-bits of the -// compact encoding is the offset of the DWARF FDE in the __eh_frame section. -// This mode is never used in object files. It is only generated by the -// linker in final linked images which have only DWARF unwind info for a -// function. -// - - -// ARM64 -// -// 1-bit: start -// 1-bit: has lsda -// 2-bit: personality index -// -// 4-bits: 4=frame-based, 3=DWARF, 2=frameless -// frameless: -// 12-bits of stack size -// frame-based: -// 4-bits D reg pairs saved -// 5-bits X reg pairs saved -// DWARF: -// 24-bits offset of DWARF FDE in __eh_frame section -// -enum { - UNWIND_ARM64_MODE_MASK = 0x0F000000, - UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, - UNWIND_ARM64_MODE_DWARF = 0x03000000, - UNWIND_ARM64_MODE_FRAME = 0x04000000, - - UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, - UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, - UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, - UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, - UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, - UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, - UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, - UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, - UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, - - UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, - UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, -}; -// For arm64 there are three modes for the compact unwind encoding: -// UNWIND_ARM64_MODE_FRAME: -// This is a standard arm64 prolog where FP/LR are immediately pushed on the -// stack, then SP is copied to FP. If there are any non-volatile registers -// saved, then are copied into the stack frame in pairs in a contiguous -// range right below the saved FP/LR pair. Any subset of the five X pairs -// and four D pairs can be saved, but the memory layout must be in register -// number order. -// UNWIND_ARM64_MODE_FRAMELESS: -// A "frameless" leaf function, where FP/LR are not saved. The return address -// remains in LR throughout the function. If any non-volatile registers -// are saved, they must be pushed onto the stack before any stack space is -// allocated for local variables. The stack sized (including any saved -// non-volatile registers) divided by 16 is encoded in the bits -// UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK. -// UNWIND_ARM64_MODE_DWARF: -// No compact unwind encoding is available. Instead the low 24-bits of the -// compact encoding is the offset of the DWARF FDE in the __eh_frame section. -// This mode is never used in object files. It is only generated by the -// linker in final linked images which have only DWARF unwind info for a -// function. -// - - - - - -//////////////////////////////////////////////////////////////////////////////// -// -// Relocatable Object Files: __LD,__compact_unwind -// -//////////////////////////////////////////////////////////////////////////////// - -// -// A compiler can generated compact unwind information for a function by adding -// a "row" to the __LD,__compact_unwind section. This section has the -// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers. -// It is removed by the new linker, so never ends up in final executables. -// This section is a table, initially with one row per function (that needs -// unwind info). The table columns and some conceptual entries are: -// -// range-start pointer to start of function/range -// range-length -// compact-unwind-encoding 32-bit encoding -// personality-function or zero if no personality function -// lsda or zero if no LSDA data -// -// The length and encoding fields are 32-bits. The other are all pointer sized. -// -// In x86_64 assembly, these entry would look like: -// -// .section __LD,__compact_unwind,regular,debug -// -// #compact unwind for _foo -// .quad _foo -// .set L1,LfooEnd-_foo -// .long L1 -// .long 0x01010001 -// .quad 0 -// .quad 0 -// -// #compact unwind for _bar -// .quad _bar -// .set L2,LbarEnd-_bar -// .long L2 -// .long 0x01020011 -// .quad __gxx_personality -// .quad except_tab1 -// -// -// Notes: There is no need for any labels in the the __compact_unwind section. -// The use of the .set directive is to force the evaluation of the -// range-length at assembly time, instead of generating relocations. -// -// To support future compiler optimizations where which non-volatile registers -// are saved changes within a function (e.g. delay saving non-volatiles until -// necessary), there can by multiple lines in the __compact_unwind table for one -// function, each with a different (non-overlapping) range and each with -// different compact unwind encodings that correspond to the non-volatiles -// saved at that range of the function. -// -// If a particular function is so wacky that there is no compact unwind way -// to encode it, then the compiler can emit traditional DWARF unwind info. -// The runtime will use which ever is available. -// -// Runtime support for compact unwind encodings are only available on 10.6 -// and later. So, the compiler should not generate it when targeting pre-10.6. - - - - -//////////////////////////////////////////////////////////////////////////////// -// -// Final Linked Images: __TEXT,__unwind_info -// -//////////////////////////////////////////////////////////////////////////////// - -// -// The __TEXT,__unwind_info section is laid out for an efficient two level lookup. -// The header of the section contains a coarse index that maps function address -// to the page (4096 byte block) containing the unwind info for that function. -// - -#define UNWIND_SECTION_VERSION 1 -struct unwind_info_section_header -{ - uint32_t version; // UNWIND_SECTION_VERSION - uint32_t commonEncodingsArraySectionOffset; - uint32_t commonEncodingsArrayCount; - uint32_t personalityArraySectionOffset; - uint32_t personalityArrayCount; - uint32_t indexSectionOffset; - uint32_t indexCount; - // compact_unwind_encoding_t[] - // uint32_t personalities[] - // unwind_info_section_header_index_entry[] - // unwind_info_section_header_lsda_index_entry[] -}; - -struct unwind_info_section_header_index_entry -{ - uint32_t functionOffset; - uint32_t secondLevelPagesSectionOffset; // section offset to start of regular or compress page - uint32_t lsdaIndexArraySectionOffset; // section offset to start of lsda_index array for this range -}; - -struct unwind_info_section_header_lsda_index_entry -{ - uint32_t functionOffset; - uint32_t lsdaOffset; -}; - -// -// There are two kinds of second level index pages: regular and compressed. -// A compressed page can hold up to 1021 entries, but it cannot be used -// if too many different encoding types are used. The regular page holds -// 511 entries. -// - -struct unwind_info_regular_second_level_entry -{ - uint32_t functionOffset; - compact_unwind_encoding_t encoding; -}; - -#define UNWIND_SECOND_LEVEL_REGULAR 2 -struct unwind_info_regular_second_level_page_header -{ - uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR - uint16_t entryPageOffset; - uint16_t entryCount; - // entry array -}; - -#define UNWIND_SECOND_LEVEL_COMPRESSED 3 -struct unwind_info_compressed_second_level_page_header -{ - uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED - uint16_t entryPageOffset; - uint16_t entryCount; - uint16_t encodingsPageOffset; - uint16_t encodingsCount; - // 32-bit entry array - // encodings array -}; - -#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF) -#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF) - - - -#endif - Property changes on: head/contrib/llvm/projects/libunwind/include/mach-o/compact_unwind_encoding.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/DwarfInstructions.hpp =================================================================== --- head/contrib/llvm/projects/libunwind/src/DwarfInstructions.hpp (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/DwarfInstructions.hpp (nonexistent) @@ -1,795 +0,0 @@ -//===-------------------------- DwarfInstructions.hpp ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Processor specific interpretation of DWARF unwind info. -// -//===----------------------------------------------------------------------===// - -#ifndef __DWARF_INSTRUCTIONS_HPP__ -#define __DWARF_INSTRUCTIONS_HPP__ - -#include -#include -#include - -#include "dwarf2.h" -#include "Registers.hpp" -#include "DwarfParser.hpp" -#include "config.h" - - -namespace libunwind { - - -/// DwarfInstructions maps abtract DWARF unwind instructions to a particular -/// architecture -template -class DwarfInstructions { -public: - typedef typename A::pint_t pint_t; - typedef typename A::sint_t sint_t; - - static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart, - R ®isters); - -private: - - enum { - DW_X86_64_RET_ADDR = 16 - }; - - enum { - DW_X86_RET_ADDR = 8 - }; - - typedef typename CFI_Parser::RegisterLocation RegisterLocation; - typedef typename CFI_Parser::PrologInfo PrologInfo; - typedef typename CFI_Parser::FDE_Info FDE_Info; - typedef typename CFI_Parser::CIE_Info CIE_Info; - - static pint_t evaluateExpression(pint_t expression, A &addressSpace, - const R ®isters, - pint_t initialStackValue); - static pint_t getSavedRegister(A &addressSpace, const R ®isters, - pint_t cfa, const RegisterLocation &savedReg); - static double getSavedFloatRegister(A &addressSpace, const R ®isters, - pint_t cfa, const RegisterLocation &savedReg); - static v128 getSavedVectorRegister(A &addressSpace, const R ®isters, - pint_t cfa, const RegisterLocation &savedReg); - - static pint_t getCFA(A &addressSpace, const PrologInfo &prolog, - const R ®isters) { - if (prolog.cfaRegister != 0) - return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) + - prolog.cfaRegisterOffset); - if (prolog.cfaExpression != 0) - return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, - registers, 0); - assert(0 && "getCFA(): unknown location"); - __builtin_unreachable(); - } -}; - - -template -typename A::pint_t DwarfInstructions::getSavedRegister( - A &addressSpace, const R ®isters, pint_t cfa, - const RegisterLocation &savedReg) { - switch (savedReg.location) { - case CFI_Parser::kRegisterInCFA: - return addressSpace.getRegister(cfa + (pint_t)savedReg.value); - - case CFI_Parser::kRegisterAtExpression: - return addressSpace.getRegister( - evaluateExpression((pint_t)savedReg.value, addressSpace, - registers, cfa)); - - case CFI_Parser::kRegisterIsExpression: - return evaluateExpression((pint_t)savedReg.value, addressSpace, - registers, cfa); - - case CFI_Parser::kRegisterInRegister: - return registers.getRegister((int)savedReg.value); - - case CFI_Parser::kRegisterUnused: - case CFI_Parser::kRegisterOffsetFromCFA: - // FIX ME - break; - } - _LIBUNWIND_ABORT("unsupported restore location for register"); -} - -template -double DwarfInstructions::getSavedFloatRegister( - A &addressSpace, const R ®isters, pint_t cfa, - const RegisterLocation &savedReg) { - switch (savedReg.location) { - case CFI_Parser::kRegisterInCFA: - return addressSpace.getDouble(cfa + (pint_t)savedReg.value); - - case CFI_Parser::kRegisterAtExpression: - return addressSpace.getDouble( - evaluateExpression((pint_t)savedReg.value, addressSpace, - registers, cfa)); - - case CFI_Parser::kRegisterIsExpression: - case CFI_Parser::kRegisterUnused: - case CFI_Parser::kRegisterOffsetFromCFA: - case CFI_Parser::kRegisterInRegister: - // FIX ME - break; - } - _LIBUNWIND_ABORT("unsupported restore location for float register"); -} - -template -v128 DwarfInstructions::getSavedVectorRegister( - A &addressSpace, const R ®isters, pint_t cfa, - const RegisterLocation &savedReg) { - switch (savedReg.location) { - case CFI_Parser::kRegisterInCFA: - return addressSpace.getVector(cfa + (pint_t)savedReg.value); - - case CFI_Parser::kRegisterAtExpression: - return addressSpace.getVector( - evaluateExpression((pint_t)savedReg.value, addressSpace, - registers, cfa)); - - case CFI_Parser::kRegisterIsExpression: - case CFI_Parser::kRegisterUnused: - case CFI_Parser::kRegisterOffsetFromCFA: - case CFI_Parser::kRegisterInRegister: - // FIX ME - break; - } - _LIBUNWIND_ABORT("unsupported restore location for vector register"); -} - -template -int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, - pint_t fdeStart, R ®isters) { - FDE_Info fdeInfo; - CIE_Info cieInfo; - if (CFI_Parser::decodeFDE(addressSpace, fdeStart, &fdeInfo, - &cieInfo) == NULL) { - PrologInfo prolog; - if (CFI_Parser::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, - R::getArch(), &prolog)) { - // get pointer to cfa (architecture specific) - pint_t cfa = getCFA(addressSpace, prolog, registers); - - // restore registers that DWARF says were saved - R newRegisters = registers; - pint_t returnAddress = 0; - const int lastReg = R::lastDwarfRegNum(); - assert(static_cast(CFI_Parser::kMaxRegisterNumber) >= lastReg && - "register range too large"); - assert(lastReg >= (int)cieInfo.returnAddressRegister && - "register range does not contain return address register"); - for (int i = 0; i <= lastReg; ++i) { - if (prolog.savedRegisters[i].location != - CFI_Parser::kRegisterUnused) { - if (registers.validFloatRegister(i)) - newRegisters.setFloatRegister( - i, getSavedFloatRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i])); - else if (registers.validVectorRegister(i)) - newRegisters.setVectorRegister( - i, getSavedVectorRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i])); - else if (i == (int)cieInfo.returnAddressRegister) - returnAddress = getSavedRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i]); - else if (registers.validRegister(i)) - newRegisters.setRegister( - i, getSavedRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i])); - else - return UNW_EBADREG; - } - } - - // By definition, the CFA is the stack pointer at the call site, so - // restoring SP means setting it to CFA. - newRegisters.setSP(cfa); - -#if defined(_LIBUNWIND_TARGET_AARCH64) - // If the target is aarch64 then the return address may have been signed - // using the v8.3 pointer authentication extensions. The original - // return address needs to be authenticated before the return address is - // restored. autia1716 is used instead of autia as autia1716 assembles - // to a NOP on pre-v8.3a architectures. - if ((R::getArch() == REGISTERS_ARM64) && - prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) { -#if !defined(_LIBUNWIND_IS_NATIVE_ONLY) - return UNW_ECROSSRASIGNING; -#else - register unsigned long long x17 __asm("x17") = returnAddress; - register unsigned long long x16 __asm("x16") = cfa; - - // These are the autia1716/autib1716 instructions. The hint instructions - // are used here as gcc does not assemble autia1716/autib1716 for pre - // armv8.3a targets. - if (cieInfo.addressesSignedWithBKey) - asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716 - else - asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716 - returnAddress = x17; -#endif - } -#endif - -#if defined(_LIBUNWIND_TARGET_SPARC) - if (R::getArch() == REGISTERS_SPARC) { - // Skip call site instruction and delay slot - returnAddress += 8; - // Skip unimp instruction if function returns a struct - if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0) - returnAddress += 4; - } -#endif - - // Return address is address after call site instruction, so setting IP to - // that does simualates a return. - newRegisters.setIP(returnAddress); - - // Simulate the step by replacing the register set with the new ones. - registers = newRegisters; - - return UNW_STEP_SUCCESS; - } - } - return UNW_EBADFRAME; -} - -template -typename A::pint_t -DwarfInstructions::evaluateExpression(pint_t expression, A &addressSpace, - const R ®isters, - pint_t initialStackValue) { - const bool log = false; - pint_t p = expression; - pint_t expressionEnd = expression + 20; // temp, until len read - pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd); - expressionEnd = p + length; - if (log) - fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n", - (uint64_t)length); - pint_t stack[100]; - pint_t *sp = stack; - *(++sp) = initialStackValue; - - while (p < expressionEnd) { - if (log) { - for (pint_t *t = sp; t > stack; --t) { - fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t)); - } - } - uint8_t opcode = addressSpace.get8(p++); - sint_t svalue, svalue2; - pint_t value; - uint32_t reg; - switch (opcode) { - case DW_OP_addr: - // push immediate address sized value - value = addressSpace.getP(p); - p += sizeof(pint_t); - *(++sp) = value; - if (log) - fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); - break; - - case DW_OP_deref: - // pop stack, dereference, push result - value = *sp--; - *(++sp) = addressSpace.getP(value); - if (log) - fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value); - break; - - case DW_OP_const1u: - // push immediate 1 byte value - value = addressSpace.get8(p); - p += 1; - *(++sp) = value; - if (log) - fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); - break; - - case DW_OP_const1s: - // push immediate 1 byte signed value - svalue = (int8_t) addressSpace.get8(p); - p += 1; - *(++sp) = (pint_t)svalue; - if (log) - fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); - break; - - case DW_OP_const2u: - // push immediate 2 byte value - value = addressSpace.get16(p); - p += 2; - *(++sp) = value; - if (log) - fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); - break; - - case DW_OP_const2s: - // push immediate 2 byte signed value - svalue = (int16_t) addressSpace.get16(p); - p += 2; - *(++sp) = (pint_t)svalue; - if (log) - fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); - break; - - case DW_OP_const4u: - // push immediate 4 byte value - value = addressSpace.get32(p); - p += 4; - *(++sp) = value; - if (log) - fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); - break; - - case DW_OP_const4s: - // push immediate 4 byte signed value - svalue = (int32_t)addressSpace.get32(p); - p += 4; - *(++sp) = (pint_t)svalue; - if (log) - fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); - break; - - case DW_OP_const8u: - // push immediate 8 byte value - value = (pint_t)addressSpace.get64(p); - p += 8; - *(++sp) = value; - if (log) - fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); - break; - - case DW_OP_const8s: - // push immediate 8 byte signed value - value = (pint_t)addressSpace.get64(p); - p += 8; - *(++sp) = value; - if (log) - fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); - break; - - case DW_OP_constu: - // push immediate ULEB128 value - value = (pint_t)addressSpace.getULEB128(p, expressionEnd); - *(++sp) = value; - if (log) - fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); - break; - - case DW_OP_consts: - // push immediate SLEB128 value - svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); - *(++sp) = (pint_t)svalue; - if (log) - fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); - break; - - case DW_OP_dup: - // push top of stack - value = *sp; - *(++sp) = value; - if (log) - fprintf(stderr, "duplicate top of stack\n"); - break; - - case DW_OP_drop: - // pop - --sp; - if (log) - fprintf(stderr, "pop top of stack\n"); - break; - - case DW_OP_over: - // dup second - value = sp[-1]; - *(++sp) = value; - if (log) - fprintf(stderr, "duplicate second in stack\n"); - break; - - case DW_OP_pick: - // pick from - reg = addressSpace.get8(p); - p += 1; - value = sp[-reg]; - *(++sp) = value; - if (log) - fprintf(stderr, "duplicate %d in stack\n", reg); - break; - - case DW_OP_swap: - // swap top two - value = sp[0]; - sp[0] = sp[-1]; - sp[-1] = value; - if (log) - fprintf(stderr, "swap top of stack\n"); - break; - - case DW_OP_rot: - // rotate top three - value = sp[0]; - sp[0] = sp[-1]; - sp[-1] = sp[-2]; - sp[-2] = value; - if (log) - fprintf(stderr, "rotate top three of stack\n"); - break; - - case DW_OP_xderef: - // pop stack, dereference, push result - value = *sp--; - *sp = *((pint_t*)value); - if (log) - fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value); - break; - - case DW_OP_abs: - svalue = (sint_t)*sp; - if (svalue < 0) - *sp = (pint_t)(-svalue); - if (log) - fprintf(stderr, "abs\n"); - break; - - case DW_OP_and: - value = *sp--; - *sp &= value; - if (log) - fprintf(stderr, "and\n"); - break; - - case DW_OP_div: - svalue = (sint_t)(*sp--); - svalue2 = (sint_t)*sp; - *sp = (pint_t)(svalue2 / svalue); - if (log) - fprintf(stderr, "div\n"); - break; - - case DW_OP_minus: - value = *sp--; - *sp = *sp - value; - if (log) - fprintf(stderr, "minus\n"); - break; - - case DW_OP_mod: - svalue = (sint_t)(*sp--); - svalue2 = (sint_t)*sp; - *sp = (pint_t)(svalue2 % svalue); - if (log) - fprintf(stderr, "module\n"); - break; - - case DW_OP_mul: - svalue = (sint_t)(*sp--); - svalue2 = (sint_t)*sp; - *sp = (pint_t)(svalue2 * svalue); - if (log) - fprintf(stderr, "mul\n"); - break; - - case DW_OP_neg: - *sp = 0 - *sp; - if (log) - fprintf(stderr, "neg\n"); - break; - - case DW_OP_not: - svalue = (sint_t)(*sp); - *sp = (pint_t)(~svalue); - if (log) - fprintf(stderr, "not\n"); - break; - - case DW_OP_or: - value = *sp--; - *sp |= value; - if (log) - fprintf(stderr, "or\n"); - break; - - case DW_OP_plus: - value = *sp--; - *sp += value; - if (log) - fprintf(stderr, "plus\n"); - break; - - case DW_OP_plus_uconst: - // pop stack, add uelb128 constant, push result - *sp += static_cast(addressSpace.getULEB128(p, expressionEnd)); - if (log) - fprintf(stderr, "add constant\n"); - break; - - case DW_OP_shl: - value = *sp--; - *sp = *sp << value; - if (log) - fprintf(stderr, "shift left\n"); - break; - - case DW_OP_shr: - value = *sp--; - *sp = *sp >> value; - if (log) - fprintf(stderr, "shift left\n"); - break; - - case DW_OP_shra: - value = *sp--; - svalue = (sint_t)*sp; - *sp = (pint_t)(svalue >> value); - if (log) - fprintf(stderr, "shift left arithmetric\n"); - break; - - case DW_OP_xor: - value = *sp--; - *sp ^= value; - if (log) - fprintf(stderr, "xor\n"); - break; - - case DW_OP_skip: - svalue = (int16_t) addressSpace.get16(p); - p += 2; - p = (pint_t)((sint_t)p + svalue); - if (log) - fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue); - break; - - case DW_OP_bra: - svalue = (int16_t) addressSpace.get16(p); - p += 2; - if (*sp--) - p = (pint_t)((sint_t)p + svalue); - if (log) - fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue); - break; - - case DW_OP_eq: - value = *sp--; - *sp = (*sp == value); - if (log) - fprintf(stderr, "eq\n"); - break; - - case DW_OP_ge: - value = *sp--; - *sp = (*sp >= value); - if (log) - fprintf(stderr, "ge\n"); - break; - - case DW_OP_gt: - value = *sp--; - *sp = (*sp > value); - if (log) - fprintf(stderr, "gt\n"); - break; - - case DW_OP_le: - value = *sp--; - *sp = (*sp <= value); - if (log) - fprintf(stderr, "le\n"); - break; - - case DW_OP_lt: - value = *sp--; - *sp = (*sp < value); - if (log) - fprintf(stderr, "lt\n"); - break; - - case DW_OP_ne: - value = *sp--; - *sp = (*sp != value); - if (log) - fprintf(stderr, "ne\n"); - break; - - case DW_OP_lit0: - case DW_OP_lit1: - case DW_OP_lit2: - case DW_OP_lit3: - case DW_OP_lit4: - case DW_OP_lit5: - case DW_OP_lit6: - case DW_OP_lit7: - case DW_OP_lit8: - case DW_OP_lit9: - case DW_OP_lit10: - case DW_OP_lit11: - case DW_OP_lit12: - case DW_OP_lit13: - case DW_OP_lit14: - case DW_OP_lit15: - case DW_OP_lit16: - case DW_OP_lit17: - case DW_OP_lit18: - case DW_OP_lit19: - case DW_OP_lit20: - case DW_OP_lit21: - case DW_OP_lit22: - case DW_OP_lit23: - case DW_OP_lit24: - case DW_OP_lit25: - case DW_OP_lit26: - case DW_OP_lit27: - case DW_OP_lit28: - case DW_OP_lit29: - case DW_OP_lit30: - case DW_OP_lit31: - value = static_cast(opcode - DW_OP_lit0); - *(++sp) = value; - if (log) - fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value); - break; - - case DW_OP_reg0: - case DW_OP_reg1: - case DW_OP_reg2: - case DW_OP_reg3: - case DW_OP_reg4: - case DW_OP_reg5: - case DW_OP_reg6: - case DW_OP_reg7: - case DW_OP_reg8: - case DW_OP_reg9: - case DW_OP_reg10: - case DW_OP_reg11: - case DW_OP_reg12: - case DW_OP_reg13: - case DW_OP_reg14: - case DW_OP_reg15: - case DW_OP_reg16: - case DW_OP_reg17: - case DW_OP_reg18: - case DW_OP_reg19: - case DW_OP_reg20: - case DW_OP_reg21: - case DW_OP_reg22: - case DW_OP_reg23: - case DW_OP_reg24: - case DW_OP_reg25: - case DW_OP_reg26: - case DW_OP_reg27: - case DW_OP_reg28: - case DW_OP_reg29: - case DW_OP_reg30: - case DW_OP_reg31: - reg = static_cast(opcode - DW_OP_reg0); - *(++sp) = registers.getRegister((int)reg); - if (log) - fprintf(stderr, "push reg %d\n", reg); - break; - - case DW_OP_regx: - reg = static_cast(addressSpace.getULEB128(p, expressionEnd)); - *(++sp) = registers.getRegister((int)reg); - if (log) - fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); - break; - - case DW_OP_breg0: - case DW_OP_breg1: - case DW_OP_breg2: - case DW_OP_breg3: - case DW_OP_breg4: - case DW_OP_breg5: - case DW_OP_breg6: - case DW_OP_breg7: - case DW_OP_breg8: - case DW_OP_breg9: - case DW_OP_breg10: - case DW_OP_breg11: - case DW_OP_breg12: - case DW_OP_breg13: - case DW_OP_breg14: - case DW_OP_breg15: - case DW_OP_breg16: - case DW_OP_breg17: - case DW_OP_breg18: - case DW_OP_breg19: - case DW_OP_breg20: - case DW_OP_breg21: - case DW_OP_breg22: - case DW_OP_breg23: - case DW_OP_breg24: - case DW_OP_breg25: - case DW_OP_breg26: - case DW_OP_breg27: - case DW_OP_breg28: - case DW_OP_breg29: - case DW_OP_breg30: - case DW_OP_breg31: - reg = static_cast(opcode - DW_OP_breg0); - svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); - svalue += static_cast(registers.getRegister((int)reg)); - *(++sp) = (pint_t)(svalue); - if (log) - fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); - break; - - case DW_OP_bregx: - reg = static_cast(addressSpace.getULEB128(p, expressionEnd)); - svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); - svalue += static_cast(registers.getRegister((int)reg)); - *(++sp) = (pint_t)(svalue); - if (log) - fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); - break; - - case DW_OP_fbreg: - _LIBUNWIND_ABORT("DW_OP_fbreg not implemented"); - break; - - case DW_OP_piece: - _LIBUNWIND_ABORT("DW_OP_piece not implemented"); - break; - - case DW_OP_deref_size: - // pop stack, dereference, push result - value = *sp--; - switch (addressSpace.get8(p++)) { - case 1: - value = addressSpace.get8(value); - break; - case 2: - value = addressSpace.get16(value); - break; - case 4: - value = addressSpace.get32(value); - break; - case 8: - value = (pint_t)addressSpace.get64(value); - break; - default: - _LIBUNWIND_ABORT("DW_OP_deref_size with bad size"); - } - *(++sp) = value; - if (log) - fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value); - break; - - case DW_OP_xderef_size: - case DW_OP_nop: - case DW_OP_push_object_addres: - case DW_OP_call2: - case DW_OP_call4: - case DW_OP_call_ref: - default: - _LIBUNWIND_ABORT("DWARF opcode not implemented"); - } - - } - if (log) - fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp); - return *sp; -} - - - -} // namespace libunwind - -#endif // __DWARF_INSTRUCTIONS_HPP__ Index: head/contrib/llvm/projects/libunwind/src/EHHeaderParser.hpp =================================================================== --- head/contrib/llvm/projects/libunwind/src/EHHeaderParser.hpp (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/EHHeaderParser.hpp (nonexistent) @@ -1,168 +0,0 @@ -//===------------------------- EHHeaderParser.hpp -------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Parses ELF .eh_frame_hdr sections. -// -//===----------------------------------------------------------------------===// - -#ifndef __EHHEADERPARSER_HPP__ -#define __EHHEADERPARSER_HPP__ - -#include "libunwind.h" - -#include "DwarfParser.hpp" - -namespace libunwind { - -/// \brief EHHeaderParser does basic parsing of an ELF .eh_frame_hdr section. -/// -/// See DWARF spec for details: -/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html -/// -template class EHHeaderParser { -public: - typedef typename A::pint_t pint_t; - - /// Information encoded in the EH frame header. - struct EHHeaderInfo { - pint_t eh_frame_ptr; - size_t fde_count; - pint_t table; - uint8_t table_enc; - }; - - static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, - EHHeaderInfo &ehHdrInfo); - static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, - uint32_t sectionLength, - typename CFI_Parser::FDE_Info *fdeInfo, - typename CFI_Parser::CIE_Info *cieInfo); - -private: - static bool decodeTableEntry(A &addressSpace, pint_t &tableEntry, - pint_t ehHdrStart, pint_t ehHdrEnd, - uint8_t tableEnc, - typename CFI_Parser::FDE_Info *fdeInfo, - typename CFI_Parser::CIE_Info *cieInfo); - static size_t getTableEntrySize(uint8_t tableEnc); -}; - -template -bool EHHeaderParser::decodeEHHdr(A &addressSpace, pint_t ehHdrStart, - pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) { - pint_t p = ehHdrStart; - uint8_t version = addressSpace.get8(p++); - if (version != 1) { - _LIBUNWIND_LOG0("Unsupported .eh_frame_hdr version"); - return false; - } - - uint8_t eh_frame_ptr_enc = addressSpace.get8(p++); - uint8_t fde_count_enc = addressSpace.get8(p++); - ehHdrInfo.table_enc = addressSpace.get8(p++); - - ehHdrInfo.eh_frame_ptr = - addressSpace.getEncodedP(p, ehHdrEnd, eh_frame_ptr_enc, ehHdrStart); - ehHdrInfo.fde_count = - fde_count_enc == DW_EH_PE_omit - ? 0 - : addressSpace.getEncodedP(p, ehHdrEnd, fde_count_enc, ehHdrStart); - ehHdrInfo.table = p; - - return true; -} - -template -bool EHHeaderParser::decodeTableEntry( - A &addressSpace, pint_t &tableEntry, pint_t ehHdrStart, pint_t ehHdrEnd, - uint8_t tableEnc, typename CFI_Parser::FDE_Info *fdeInfo, - typename CFI_Parser::CIE_Info *cieInfo) { - // Have to decode the whole FDE for the PC range anyway, so just throw away - // the PC start. - addressSpace.getEncodedP(tableEntry, ehHdrEnd, tableEnc, ehHdrStart); - pint_t fde = - addressSpace.getEncodedP(tableEntry, ehHdrEnd, tableEnc, ehHdrStart); - const char *message = - CFI_Parser::decodeFDE(addressSpace, fde, fdeInfo, cieInfo); - if (message != NULL) { - _LIBUNWIND_DEBUG_LOG("EHHeaderParser::decodeTableEntry: bad fde: %s", - message); - return false; - } - - return true; -} - -template -bool EHHeaderParser::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, - uint32_t sectionLength, - typename CFI_Parser::FDE_Info *fdeInfo, - typename CFI_Parser::CIE_Info *cieInfo) { - pint_t ehHdrEnd = ehHdrStart + sectionLength; - - EHHeaderParser::EHHeaderInfo hdrInfo; - if (!EHHeaderParser::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd, - hdrInfo)) - return false; - - size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc); - pint_t tableEntry; - - size_t low = 0; - for (size_t len = hdrInfo.fde_count; len > 1;) { - size_t mid = low + (len / 2); - tableEntry = hdrInfo.table + mid * tableEntrySize; - pint_t start = addressSpace.getEncodedP(tableEntry, ehHdrEnd, - hdrInfo.table_enc, ehHdrStart); - - if (start == pc) { - low = mid; - break; - } else if (start < pc) { - low = mid; - len -= (len / 2); - } else { - len /= 2; - } - } - - tableEntry = hdrInfo.table + low * tableEntrySize; - if (decodeTableEntry(addressSpace, tableEntry, ehHdrStart, ehHdrEnd, - hdrInfo.table_enc, fdeInfo, cieInfo)) { - if (pc >= fdeInfo->pcStart && pc < fdeInfo->pcEnd) - return true; - } - - return false; -} - -template -size_t EHHeaderParser::getTableEntrySize(uint8_t tableEnc) { - switch (tableEnc & 0x0f) { - case DW_EH_PE_sdata2: - case DW_EH_PE_udata2: - return 4; - case DW_EH_PE_sdata4: - case DW_EH_PE_udata4: - return 8; - case DW_EH_PE_sdata8: - case DW_EH_PE_udata8: - return 16; - case DW_EH_PE_sleb128: - case DW_EH_PE_uleb128: - _LIBUNWIND_ABORT("Can't binary search on variable length encoded data."); - case DW_EH_PE_omit: - return 0; - default: - _LIBUNWIND_ABORT("Unknown DWARF encoding for search table."); - } -} - -} - -#endif Index: head/contrib/llvm/projects/libunwind/src/Registers.hpp =================================================================== --- head/contrib/llvm/projects/libunwind/src/Registers.hpp (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/Registers.hpp (nonexistent) @@ -1,3785 +0,0 @@ -//===----------------------------- Registers.hpp --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Models register sets for supported processors. -// -//===----------------------------------------------------------------------===// - -#ifndef __REGISTERS_HPP__ -#define __REGISTERS_HPP__ - -#include -#include - -#include "libunwind.h" -#include "config.h" - -namespace libunwind { - -// For emulating 128-bit registers -struct v128 { uint32_t vec[4]; }; - -enum { - REGISTERS_X86, - REGISTERS_X86_64, - REGISTERS_PPC, - REGISTERS_PPC64, - REGISTERS_ARM64, - REGISTERS_ARM, - REGISTERS_OR1K, - REGISTERS_RISCV, - REGISTERS_MIPS_O32, - REGISTERS_MIPS_NEWABI, - REGISTERS_SPARC, -}; - -#if defined(_LIBUNWIND_TARGET_I386) -/// Registers_x86 holds the register state of a thread in a 32-bit intel -/// process. -class _LIBUNWIND_HIDDEN Registers_x86 { -public: - Registers_x86(); - Registers_x86(const void *registers); - - bool validRegister(int num) const; - uint32_t getRegister(int num) const; - void setRegister(int num, uint32_t value); - bool validFloatRegister(int) const { return false; } - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); - bool validVectorRegister(int) const { return false; } - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - static const char *getRegisterName(int num); - void jumpto(); - static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; } - static int getArch() { return REGISTERS_X86; } - - uint32_t getSP() const { return _registers.__esp; } - void setSP(uint32_t value) { _registers.__esp = value; } - uint32_t getIP() const { return _registers.__eip; } - void setIP(uint32_t value) { _registers.__eip = value; } - uint32_t getEBP() const { return _registers.__ebp; } - void setEBP(uint32_t value) { _registers.__ebp = value; } - uint32_t getEBX() const { return _registers.__ebx; } - void setEBX(uint32_t value) { _registers.__ebx = value; } - uint32_t getECX() const { return _registers.__ecx; } - void setECX(uint32_t value) { _registers.__ecx = value; } - uint32_t getEDX() const { return _registers.__edx; } - void setEDX(uint32_t value) { _registers.__edx = value; } - uint32_t getESI() const { return _registers.__esi; } - void setESI(uint32_t value) { _registers.__esi = value; } - uint32_t getEDI() const { return _registers.__edi; } - void setEDI(uint32_t value) { _registers.__edi = value; } - -private: - struct GPRs { - unsigned int __eax; - unsigned int __ebx; - unsigned int __ecx; - unsigned int __edx; - unsigned int __edi; - unsigned int __esi; - unsigned int __ebp; - unsigned int __esp; - unsigned int __ss; - unsigned int __eflags; - unsigned int __eip; - unsigned int __cs; - unsigned int __ds; - unsigned int __es; - unsigned int __fs; - unsigned int __gs; - }; - - GPRs _registers; -}; - -inline Registers_x86::Registers_x86(const void *registers) { - static_assert((check_fit::does_fit), - "x86 registers do not fit into unw_context_t"); - memcpy(&_registers, registers, sizeof(_registers)); -} - -inline Registers_x86::Registers_x86() { - memset(&_registers, 0, sizeof(_registers)); -} - -inline bool Registers_x86::validRegister(int regNum) const { - if (regNum == UNW_REG_IP) - return true; - if (regNum == UNW_REG_SP) - return true; - if (regNum < 0) - return false; - if (regNum > 7) - return false; - return true; -} - -inline uint32_t Registers_x86::getRegister(int regNum) const { - switch (regNum) { - case UNW_REG_IP: - return _registers.__eip; - case UNW_REG_SP: - return _registers.__esp; - case UNW_X86_EAX: - return _registers.__eax; - case UNW_X86_ECX: - return _registers.__ecx; - case UNW_X86_EDX: - return _registers.__edx; - case UNW_X86_EBX: - return _registers.__ebx; -#if !defined(__APPLE__) - case UNW_X86_ESP: -#else - case UNW_X86_EBP: -#endif - return _registers.__ebp; -#if !defined(__APPLE__) - case UNW_X86_EBP: -#else - case UNW_X86_ESP: -#endif - return _registers.__esp; - case UNW_X86_ESI: - return _registers.__esi; - case UNW_X86_EDI: - return _registers.__edi; - } - _LIBUNWIND_ABORT("unsupported x86 register"); -} - -inline void Registers_x86::setRegister(int regNum, uint32_t value) { - switch (regNum) { - case UNW_REG_IP: - _registers.__eip = value; - return; - case UNW_REG_SP: - _registers.__esp = value; - return; - case UNW_X86_EAX: - _registers.__eax = value; - return; - case UNW_X86_ECX: - _registers.__ecx = value; - return; - case UNW_X86_EDX: - _registers.__edx = value; - return; - case UNW_X86_EBX: - _registers.__ebx = value; - return; -#if !defined(__APPLE__) - case UNW_X86_ESP: -#else - case UNW_X86_EBP: -#endif - _registers.__ebp = value; - return; -#if !defined(__APPLE__) - case UNW_X86_EBP: -#else - case UNW_X86_ESP: -#endif - _registers.__esp = value; - return; - case UNW_X86_ESI: - _registers.__esi = value; - return; - case UNW_X86_EDI: - _registers.__edi = value; - return; - } - _LIBUNWIND_ABORT("unsupported x86 register"); -} - -inline const char *Registers_x86::getRegisterName(int regNum) { - switch (regNum) { - case UNW_REG_IP: - return "ip"; - case UNW_REG_SP: - return "esp"; - case UNW_X86_EAX: - return "eax"; - case UNW_X86_ECX: - return "ecx"; - case UNW_X86_EDX: - return "edx"; - case UNW_X86_EBX: - return "ebx"; - case UNW_X86_EBP: - return "ebp"; - case UNW_X86_ESP: - return "esp"; - case UNW_X86_ESI: - return "esi"; - case UNW_X86_EDI: - return "edi"; - default: - return "unknown register"; - } -} - -inline double Registers_x86::getFloatRegister(int) const { - _LIBUNWIND_ABORT("no x86 float registers"); -} - -inline void Registers_x86::setFloatRegister(int, double) { - _LIBUNWIND_ABORT("no x86 float registers"); -} - -inline v128 Registers_x86::getVectorRegister(int) const { - _LIBUNWIND_ABORT("no x86 vector registers"); -} - -inline void Registers_x86::setVectorRegister(int, v128) { - _LIBUNWIND_ABORT("no x86 vector registers"); -} -#endif // _LIBUNWIND_TARGET_I386 - - -#if defined(_LIBUNWIND_TARGET_X86_64) -/// Registers_x86_64 holds the register state of a thread in a 64-bit intel -/// process. -class _LIBUNWIND_HIDDEN Registers_x86_64 { -public: - Registers_x86_64(); - Registers_x86_64(const void *registers); - - bool validRegister(int num) const; - uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); - bool validFloatRegister(int) const { return false; } - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); - bool validVectorRegister(int) const; - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - static const char *getRegisterName(int num); - void jumpto(); - static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; } - static int getArch() { return REGISTERS_X86_64; } - - uint64_t getSP() const { return _registers.__rsp; } - void setSP(uint64_t value) { _registers.__rsp = value; } - uint64_t getIP() const { return _registers.__rip; } - void setIP(uint64_t value) { _registers.__rip = value; } - uint64_t getRBP() const { return _registers.__rbp; } - void setRBP(uint64_t value) { _registers.__rbp = value; } - uint64_t getRBX() const { return _registers.__rbx; } - void setRBX(uint64_t value) { _registers.__rbx = value; } - uint64_t getR12() const { return _registers.__r12; } - void setR12(uint64_t value) { _registers.__r12 = value; } - uint64_t getR13() const { return _registers.__r13; } - void setR13(uint64_t value) { _registers.__r13 = value; } - uint64_t getR14() const { return _registers.__r14; } - void setR14(uint64_t value) { _registers.__r14 = value; } - uint64_t getR15() const { return _registers.__r15; } - void setR15(uint64_t value) { _registers.__r15 = value; } - -private: - struct GPRs { - uint64_t __rax; - uint64_t __rbx; - uint64_t __rcx; - uint64_t __rdx; - uint64_t __rdi; - uint64_t __rsi; - uint64_t __rbp; - uint64_t __rsp; - uint64_t __r8; - uint64_t __r9; - uint64_t __r10; - uint64_t __r11; - uint64_t __r12; - uint64_t __r13; - uint64_t __r14; - uint64_t __r15; - uint64_t __rip; - uint64_t __rflags; - uint64_t __cs; - uint64_t __fs; - uint64_t __gs; -#if defined(_WIN64) - uint64_t __padding; // 16-byte align -#endif - }; - GPRs _registers; -#if defined(_WIN64) - v128 _xmm[16]; -#endif -}; - -inline Registers_x86_64::Registers_x86_64(const void *registers) { - static_assert((check_fit::does_fit), - "x86_64 registers do not fit into unw_context_t"); - memcpy(&_registers, registers, sizeof(_registers)); -} - -inline Registers_x86_64::Registers_x86_64() { - memset(&_registers, 0, sizeof(_registers)); -} - -inline bool Registers_x86_64::validRegister(int regNum) const { - if (regNum == UNW_REG_IP) - return true; - if (regNum == UNW_REG_SP) - return true; - if (regNum < 0) - return false; - if (regNum > 15) - return false; - return true; -} - -inline uint64_t Registers_x86_64::getRegister(int regNum) const { - switch (regNum) { - case UNW_REG_IP: - return _registers.__rip; - case UNW_REG_SP: - return _registers.__rsp; - case UNW_X86_64_RAX: - return _registers.__rax; - case UNW_X86_64_RDX: - return _registers.__rdx; - case UNW_X86_64_RCX: - return _registers.__rcx; - case UNW_X86_64_RBX: - return _registers.__rbx; - case UNW_X86_64_RSI: - return _registers.__rsi; - case UNW_X86_64_RDI: - return _registers.__rdi; - case UNW_X86_64_RBP: - return _registers.__rbp; - case UNW_X86_64_RSP: - return _registers.__rsp; - case UNW_X86_64_R8: - return _registers.__r8; - case UNW_X86_64_R9: - return _registers.__r9; - case UNW_X86_64_R10: - return _registers.__r10; - case UNW_X86_64_R11: - return _registers.__r11; - case UNW_X86_64_R12: - return _registers.__r12; - case UNW_X86_64_R13: - return _registers.__r13; - case UNW_X86_64_R14: - return _registers.__r14; - case UNW_X86_64_R15: - return _registers.__r15; - } - _LIBUNWIND_ABORT("unsupported x86_64 register"); -} - -inline void Registers_x86_64::setRegister(int regNum, uint64_t value) { - switch (regNum) { - case UNW_REG_IP: - _registers.__rip = value; - return; - case UNW_REG_SP: - _registers.__rsp = value; - return; - case UNW_X86_64_RAX: - _registers.__rax = value; - return; - case UNW_X86_64_RDX: - _registers.__rdx = value; - return; - case UNW_X86_64_RCX: - _registers.__rcx = value; - return; - case UNW_X86_64_RBX: - _registers.__rbx = value; - return; - case UNW_X86_64_RSI: - _registers.__rsi = value; - return; - case UNW_X86_64_RDI: - _registers.__rdi = value; - return; - case UNW_X86_64_RBP: - _registers.__rbp = value; - return; - case UNW_X86_64_RSP: - _registers.__rsp = value; - return; - case UNW_X86_64_R8: - _registers.__r8 = value; - return; - case UNW_X86_64_R9: - _registers.__r9 = value; - return; - case UNW_X86_64_R10: - _registers.__r10 = value; - return; - case UNW_X86_64_R11: - _registers.__r11 = value; - return; - case UNW_X86_64_R12: - _registers.__r12 = value; - return; - case UNW_X86_64_R13: - _registers.__r13 = value; - return; - case UNW_X86_64_R14: - _registers.__r14 = value; - return; - case UNW_X86_64_R15: - _registers.__r15 = value; - return; - } - _LIBUNWIND_ABORT("unsupported x86_64 register"); -} - -inline const char *Registers_x86_64::getRegisterName(int regNum) { - switch (regNum) { - case UNW_REG_IP: - return "rip"; - case UNW_REG_SP: - return "rsp"; - case UNW_X86_64_RAX: - return "rax"; - case UNW_X86_64_RDX: - return "rdx"; - case UNW_X86_64_RCX: - return "rcx"; - case UNW_X86_64_RBX: - return "rbx"; - case UNW_X86_64_RSI: - return "rsi"; - case UNW_X86_64_RDI: - return "rdi"; - case UNW_X86_64_RBP: - return "rbp"; - case UNW_X86_64_RSP: - return "rsp"; - case UNW_X86_64_R8: - return "r8"; - case UNW_X86_64_R9: - return "r9"; - case UNW_X86_64_R10: - return "r10"; - case UNW_X86_64_R11: - return "r11"; - case UNW_X86_64_R12: - return "r12"; - case UNW_X86_64_R13: - return "r13"; - case UNW_X86_64_R14: - return "r14"; - case UNW_X86_64_R15: - return "r15"; - case UNW_X86_64_XMM0: - return "xmm0"; - case UNW_X86_64_XMM1: - return "xmm1"; - case UNW_X86_64_XMM2: - return "xmm2"; - case UNW_X86_64_XMM3: - return "xmm3"; - case UNW_X86_64_XMM4: - return "xmm4"; - case UNW_X86_64_XMM5: - return "xmm5"; - case UNW_X86_64_XMM6: - return "xmm6"; - case UNW_X86_64_XMM7: - return "xmm7"; - case UNW_X86_64_XMM8: - return "xmm8"; - case UNW_X86_64_XMM9: - return "xmm9"; - case UNW_X86_64_XMM10: - return "xmm10"; - case UNW_X86_64_XMM11: - return "xmm11"; - case UNW_X86_64_XMM12: - return "xmm12"; - case UNW_X86_64_XMM13: - return "xmm13"; - case UNW_X86_64_XMM14: - return "xmm14"; - case UNW_X86_64_XMM15: - return "xmm15"; - default: - return "unknown register"; - } -} - -inline double Registers_x86_64::getFloatRegister(int) const { - _LIBUNWIND_ABORT("no x86_64 float registers"); -} - -inline void Registers_x86_64::setFloatRegister(int, double) { - _LIBUNWIND_ABORT("no x86_64 float registers"); -} - -inline bool Registers_x86_64::validVectorRegister(int regNum) const { -#if defined(_WIN64) - if (regNum < UNW_X86_64_XMM0) - return false; - if (regNum > UNW_X86_64_XMM15) - return false; - return true; -#else - (void)regNum; // suppress unused parameter warning - return false; -#endif -} - -inline v128 Registers_x86_64::getVectorRegister(int regNum) const { -#if defined(_WIN64) - assert(validVectorRegister(regNum)); - return _xmm[regNum - UNW_X86_64_XMM0]; -#else - (void)regNum; // suppress unused parameter warning - _LIBUNWIND_ABORT("no x86_64 vector registers"); -#endif -} - -inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) { -#if defined(_WIN64) - assert(validVectorRegister(regNum)); - _xmm[regNum - UNW_X86_64_XMM0] = value; -#else - (void)regNum; (void)value; // suppress unused parameter warnings - _LIBUNWIND_ABORT("no x86_64 vector registers"); -#endif -} -#endif // _LIBUNWIND_TARGET_X86_64 - - -#if defined(_LIBUNWIND_TARGET_PPC) -/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC -/// process. -class _LIBUNWIND_HIDDEN Registers_ppc { -public: - Registers_ppc(); - Registers_ppc(const void *registers); - - bool validRegister(int num) const; - uint32_t getRegister(int num) const; - void setRegister(int num, uint32_t value); - bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); - bool validVectorRegister(int num) const; - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - static const char *getRegisterName(int num); - void jumpto(); - static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; } - static int getArch() { return REGISTERS_PPC; } - - uint64_t getSP() const { return _registers.__r1; } - void setSP(uint32_t value) { _registers.__r1 = value; } - uint64_t getIP() const { return _registers.__srr0; } - void setIP(uint32_t value) { _registers.__srr0 = value; } - -private: - struct ppc_thread_state_t { - unsigned int __srr0; /* Instruction address register (PC) */ - unsigned int __srr1; /* Machine state register (supervisor) */ - unsigned int __r0; - unsigned int __r1; - unsigned int __r2; - unsigned int __r3; - unsigned int __r4; - unsigned int __r5; - unsigned int __r6; - unsigned int __r7; - unsigned int __r8; - unsigned int __r9; - unsigned int __r10; - unsigned int __r11; - unsigned int __r12; - unsigned int __r13; - unsigned int __r14; - unsigned int __r15; - unsigned int __r16; - unsigned int __r17; - unsigned int __r18; - unsigned int __r19; - unsigned int __r20; - unsigned int __r21; - unsigned int __r22; - unsigned int __r23; - unsigned int __r24; - unsigned int __r25; - unsigned int __r26; - unsigned int __r27; - unsigned int __r28; - unsigned int __r29; - unsigned int __r30; - unsigned int __r31; - unsigned int __cr; /* Condition register */ - unsigned int __xer; /* User's integer exception register */ - unsigned int __lr; /* Link register */ - unsigned int __ctr; /* Count register */ - unsigned int __mq; /* MQ register (601 only) */ - unsigned int __vrsave; /* Vector Save Register */ - }; - - struct ppc_float_state_t { - double __fpregs[32]; - - unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */ - unsigned int __fpscr; /* floating point status register */ - }; - - ppc_thread_state_t _registers; - ppc_float_state_t _floatRegisters; - v128 _vectorRegisters[32]; // offset 424 -}; - -inline Registers_ppc::Registers_ppc(const void *registers) { - static_assert((check_fit::does_fit), - "ppc registers do not fit into unw_context_t"); - memcpy(&_registers, static_cast(registers), - sizeof(_registers)); - static_assert(sizeof(ppc_thread_state_t) == 160, - "expected float register offset to be 160"); - memcpy(&_floatRegisters, - static_cast(registers) + sizeof(ppc_thread_state_t), - sizeof(_floatRegisters)); - static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424, - "expected vector register offset to be 424 bytes"); - memcpy(_vectorRegisters, - static_cast(registers) + sizeof(ppc_thread_state_t) + - sizeof(ppc_float_state_t), - sizeof(_vectorRegisters)); -} - -inline Registers_ppc::Registers_ppc() { - memset(&_registers, 0, sizeof(_registers)); - memset(&_floatRegisters, 0, sizeof(_floatRegisters)); - memset(&_vectorRegisters, 0, sizeof(_vectorRegisters)); -} - -inline bool Registers_ppc::validRegister(int regNum) const { - if (regNum == UNW_REG_IP) - return true; - if (regNum == UNW_REG_SP) - return true; - if (regNum == UNW_PPC_VRSAVE) - return true; - if (regNum < 0) - return false; - if (regNum <= UNW_PPC_R31) - return true; - if (regNum == UNW_PPC_MQ) - return true; - if (regNum == UNW_PPC_LR) - return true; - if (regNum == UNW_PPC_CTR) - return true; - if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7)) - return true; - return false; -} - -inline uint32_t Registers_ppc::getRegister(int regNum) const { - switch (regNum) { - case UNW_REG_IP: - return _registers.__srr0; - case UNW_REG_SP: - return _registers.__r1; - case UNW_PPC_R0: - return _registers.__r0; - case UNW_PPC_R1: - return _registers.__r1; - case UNW_PPC_R2: - return _registers.__r2; - case UNW_PPC_R3: - return _registers.__r3; - case UNW_PPC_R4: - return _registers.__r4; - case UNW_PPC_R5: - return _registers.__r5; - case UNW_PPC_R6: - return _registers.__r6; - case UNW_PPC_R7: - return _registers.__r7; - case UNW_PPC_R8: - return _registers.__r8; - case UNW_PPC_R9: - return _registers.__r9; - case UNW_PPC_R10: - return _registers.__r10; - case UNW_PPC_R11: - return _registers.__r11; - case UNW_PPC_R12: - return _registers.__r12; - case UNW_PPC_R13: - return _registers.__r13; - case UNW_PPC_R14: - return _registers.__r14; - case UNW_PPC_R15: - return _registers.__r15; - case UNW_PPC_R16: - return _registers.__r16; - case UNW_PPC_R17: - return _registers.__r17; - case UNW_PPC_R18: - return _registers.__r18; - case UNW_PPC_R19: - return _registers.__r19; - case UNW_PPC_R20: - return _registers.__r20; - case UNW_PPC_R21: - return _registers.__r21; - case UNW_PPC_R22: - return _registers.__r22; - case UNW_PPC_R23: - return _registers.__r23; - case UNW_PPC_R24: - return _registers.__r24; - case UNW_PPC_R25: - return _registers.__r25; - case UNW_PPC_R26: - return _registers.__r26; - case UNW_PPC_R27: - return _registers.__r27; - case UNW_PPC_R28: - return _registers.__r28; - case UNW_PPC_R29: - return _registers.__r29; - case UNW_PPC_R30: - return _registers.__r30; - case UNW_PPC_R31: - return _registers.__r31; - case UNW_PPC_LR: - return _registers.__lr; - case UNW_PPC_CR0: - return (_registers.__cr & 0xF0000000); - case UNW_PPC_CR1: - return (_registers.__cr & 0x0F000000); - case UNW_PPC_CR2: - return (_registers.__cr & 0x00F00000); - case UNW_PPC_CR3: - return (_registers.__cr & 0x000F0000); - case UNW_PPC_CR4: - return (_registers.__cr & 0x0000F000); - case UNW_PPC_CR5: - return (_registers.__cr & 0x00000F00); - case UNW_PPC_CR6: - return (_registers.__cr & 0x000000F0); - case UNW_PPC_CR7: - return (_registers.__cr & 0x0000000F); - case UNW_PPC_VRSAVE: - return _registers.__vrsave; - } - _LIBUNWIND_ABORT("unsupported ppc register"); -} - -inline void Registers_ppc::setRegister(int regNum, uint32_t value) { - //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value); - switch (regNum) { - case UNW_REG_IP: - _registers.__srr0 = value; - return; - case UNW_REG_SP: - _registers.__r1 = value; - return; - case UNW_PPC_R0: - _registers.__r0 = value; - return; - case UNW_PPC_R1: - _registers.__r1 = value; - return; - case UNW_PPC_R2: - _registers.__r2 = value; - return; - case UNW_PPC_R3: - _registers.__r3 = value; - return; - case UNW_PPC_R4: - _registers.__r4 = value; - return; - case UNW_PPC_R5: - _registers.__r5 = value; - return; - case UNW_PPC_R6: - _registers.__r6 = value; - return; - case UNW_PPC_R7: - _registers.__r7 = value; - return; - case UNW_PPC_R8: - _registers.__r8 = value; - return; - case UNW_PPC_R9: - _registers.__r9 = value; - return; - case UNW_PPC_R10: - _registers.__r10 = value; - return; - case UNW_PPC_R11: - _registers.__r11 = value; - return; - case UNW_PPC_R12: - _registers.__r12 = value; - return; - case UNW_PPC_R13: - _registers.__r13 = value; - return; - case UNW_PPC_R14: - _registers.__r14 = value; - return; - case UNW_PPC_R15: - _registers.__r15 = value; - return; - case UNW_PPC_R16: - _registers.__r16 = value; - return; - case UNW_PPC_R17: - _registers.__r17 = value; - return; - case UNW_PPC_R18: - _registers.__r18 = value; - return; - case UNW_PPC_R19: - _registers.__r19 = value; - return; - case UNW_PPC_R20: - _registers.__r20 = value; - return; - case UNW_PPC_R21: - _registers.__r21 = value; - return; - case UNW_PPC_R22: - _registers.__r22 = value; - return; - case UNW_PPC_R23: - _registers.__r23 = value; - return; - case UNW_PPC_R24: - _registers.__r24 = value; - return; - case UNW_PPC_R25: - _registers.__r25 = value; - return; - case UNW_PPC_R26: - _registers.__r26 = value; - return; - case UNW_PPC_R27: - _registers.__r27 = value; - return; - case UNW_PPC_R28: - _registers.__r28 = value; - return; - case UNW_PPC_R29: - _registers.__r29 = value; - return; - case UNW_PPC_R30: - _registers.__r30 = value; - return; - case UNW_PPC_R31: - _registers.__r31 = value; - return; - case UNW_PPC_MQ: - _registers.__mq = value; - return; - case UNW_PPC_LR: - _registers.__lr = value; - return; - case UNW_PPC_CTR: - _registers.__ctr = value; - return; - case UNW_PPC_CR0: - _registers.__cr &= 0x0FFFFFFF; - _registers.__cr |= (value & 0xF0000000); - return; - case UNW_PPC_CR1: - _registers.__cr &= 0xF0FFFFFF; - _registers.__cr |= (value & 0x0F000000); - return; - case UNW_PPC_CR2: - _registers.__cr &= 0xFF0FFFFF; - _registers.__cr |= (value & 0x00F00000); - return; - case UNW_PPC_CR3: - _registers.__cr &= 0xFFF0FFFF; - _registers.__cr |= (value & 0x000F0000); - return; - case UNW_PPC_CR4: - _registers.__cr &= 0xFFFF0FFF; - _registers.__cr |= (value & 0x0000F000); - return; - case UNW_PPC_CR5: - _registers.__cr &= 0xFFFFF0FF; - _registers.__cr |= (value & 0x00000F00); - return; - case UNW_PPC_CR6: - _registers.__cr &= 0xFFFFFF0F; - _registers.__cr |= (value & 0x000000F0); - return; - case UNW_PPC_CR7: - _registers.__cr &= 0xFFFFFFF0; - _registers.__cr |= (value & 0x0000000F); - return; - case UNW_PPC_VRSAVE: - _registers.__vrsave = value; - return; - // not saved - return; - case UNW_PPC_XER: - _registers.__xer = value; - return; - case UNW_PPC_AP: - case UNW_PPC_VSCR: - case UNW_PPC_SPEFSCR: - // not saved - return; - } - _LIBUNWIND_ABORT("unsupported ppc register"); -} - -inline bool Registers_ppc::validFloatRegister(int regNum) const { - if (regNum < UNW_PPC_F0) - return false; - if (regNum > UNW_PPC_F31) - return false; - return true; -} - -inline double Registers_ppc::getFloatRegister(int regNum) const { - assert(validFloatRegister(regNum)); - return _floatRegisters.__fpregs[regNum - UNW_PPC_F0]; -} - -inline void Registers_ppc::setFloatRegister(int regNum, double value) { - assert(validFloatRegister(regNum)); - _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value; -} - -inline bool Registers_ppc::validVectorRegister(int regNum) const { - if (regNum < UNW_PPC_V0) - return false; - if (regNum > UNW_PPC_V31) - return false; - return true; -} - -inline v128 Registers_ppc::getVectorRegister(int regNum) const { - assert(validVectorRegister(regNum)); - v128 result = _vectorRegisters[regNum - UNW_PPC_V0]; - return result; -} - -inline void Registers_ppc::setVectorRegister(int regNum, v128 value) { - assert(validVectorRegister(regNum)); - _vectorRegisters[regNum - UNW_PPC_V0] = value; -} - -inline const char *Registers_ppc::getRegisterName(int regNum) { - switch (regNum) { - case UNW_REG_IP: - return "ip"; - case UNW_REG_SP: - return "sp"; - case UNW_PPC_R0: - return "r0"; - case UNW_PPC_R1: - return "r1"; - case UNW_PPC_R2: - return "r2"; - case UNW_PPC_R3: - return "r3"; - case UNW_PPC_R4: - return "r4"; - case UNW_PPC_R5: - return "r5"; - case UNW_PPC_R6: - return "r6"; - case UNW_PPC_R7: - return "r7"; - case UNW_PPC_R8: - return "r8"; - case UNW_PPC_R9: - return "r9"; - case UNW_PPC_R10: - return "r10"; - case UNW_PPC_R11: - return "r11"; - case UNW_PPC_R12: - return "r12"; - case UNW_PPC_R13: - return "r13"; - case UNW_PPC_R14: - return "r14"; - case UNW_PPC_R15: - return "r15"; - case UNW_PPC_R16: - return "r16"; - case UNW_PPC_R17: - return "r17"; - case UNW_PPC_R18: - return "r18"; - case UNW_PPC_R19: - return "r19"; - case UNW_PPC_R20: - return "r20"; - case UNW_PPC_R21: - return "r21"; - case UNW_PPC_R22: - return "r22"; - case UNW_PPC_R23: - return "r23"; - case UNW_PPC_R24: - return "r24"; - case UNW_PPC_R25: - return "r25"; - case UNW_PPC_R26: - return "r26"; - case UNW_PPC_R27: - return "r27"; - case UNW_PPC_R28: - return "r28"; - case UNW_PPC_R29: - return "r29"; - case UNW_PPC_R30: - return "r30"; - case UNW_PPC_R31: - return "r31"; - case UNW_PPC_F0: - return "fp0"; - case UNW_PPC_F1: - return "fp1"; - case UNW_PPC_F2: - return "fp2"; - case UNW_PPC_F3: - return "fp3"; - case UNW_PPC_F4: - return "fp4"; - case UNW_PPC_F5: - return "fp5"; - case UNW_PPC_F6: - return "fp6"; - case UNW_PPC_F7: - return "fp7"; - case UNW_PPC_F8: - return "fp8"; - case UNW_PPC_F9: - return "fp9"; - case UNW_PPC_F10: - return "fp10"; - case UNW_PPC_F11: - return "fp11"; - case UNW_PPC_F12: - return "fp12"; - case UNW_PPC_F13: - return "fp13"; - case UNW_PPC_F14: - return "fp14"; - case UNW_PPC_F15: - return "fp15"; - case UNW_PPC_F16: - return "fp16"; - case UNW_PPC_F17: - return "fp17"; - case UNW_PPC_F18: - return "fp18"; - case UNW_PPC_F19: - return "fp19"; - case UNW_PPC_F20: - return "fp20"; - case UNW_PPC_F21: - return "fp21"; - case UNW_PPC_F22: - return "fp22"; - case UNW_PPC_F23: - return "fp23"; - case UNW_PPC_F24: - return "fp24"; - case UNW_PPC_F25: - return "fp25"; - case UNW_PPC_F26: - return "fp26"; - case UNW_PPC_F27: - return "fp27"; - case UNW_PPC_F28: - return "fp28"; - case UNW_PPC_F29: - return "fp29"; - case UNW_PPC_F30: - return "fp30"; - case UNW_PPC_F31: - return "fp31"; - case UNW_PPC_LR: - return "lr"; - default: - return "unknown register"; - } - -} -#endif // _LIBUNWIND_TARGET_PPC - -#if defined(_LIBUNWIND_TARGET_PPC64) -/// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC -/// process. -class _LIBUNWIND_HIDDEN Registers_ppc64 { -public: - Registers_ppc64(); - Registers_ppc64(const void *registers); - - bool validRegister(int num) const; - uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); - bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); - bool validVectorRegister(int num) const; - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - static const char *getRegisterName(int num); - void jumpto(); - static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; } - static int getArch() { return REGISTERS_PPC64; } - - uint64_t getSP() const { return _registers.__r1; } - void setSP(uint64_t value) { _registers.__r1 = value; } - uint64_t getIP() const { return _registers.__srr0; } - void setIP(uint64_t value) { _registers.__srr0 = value; } - -private: - struct ppc64_thread_state_t { - uint64_t __srr0; // Instruction address register (PC) - uint64_t __srr1; // Machine state register (supervisor) - uint64_t __r0; - uint64_t __r1; - uint64_t __r2; - uint64_t __r3; - uint64_t __r4; - uint64_t __r5; - uint64_t __r6; - uint64_t __r7; - uint64_t __r8; - uint64_t __r9; - uint64_t __r10; - uint64_t __r11; - uint64_t __r12; - uint64_t __r13; - uint64_t __r14; - uint64_t __r15; - uint64_t __r16; - uint64_t __r17; - uint64_t __r18; - uint64_t __r19; - uint64_t __r20; - uint64_t __r21; - uint64_t __r22; - uint64_t __r23; - uint64_t __r24; - uint64_t __r25; - uint64_t __r26; - uint64_t __r27; - uint64_t __r28; - uint64_t __r29; - uint64_t __r30; - uint64_t __r31; - uint64_t __cr; // Condition register - uint64_t __xer; // User's integer exception register - uint64_t __lr; // Link register - uint64_t __ctr; // Count register - uint64_t __vrsave; // Vector Save Register - }; - - union ppc64_vsr_t { - struct asfloat_s { - double f; - uint64_t v2; - } asfloat; - v128 v; - }; - - ppc64_thread_state_t _registers; - ppc64_vsr_t _vectorScalarRegisters[64]; - - static int getVectorRegNum(int num); -}; - -inline Registers_ppc64::Registers_ppc64(const void *registers) { - static_assert((check_fit::does_fit), - "ppc64 registers do not fit into unw_context_t"); - memcpy(&_registers, static_cast(registers), - sizeof(_registers)); - static_assert(sizeof(_registers) == 312, - "expected vector scalar register offset to be 312"); - memcpy(&_vectorScalarRegisters, - static_cast(registers) + sizeof(_registers), - sizeof(_vectorScalarRegisters)); - static_assert(sizeof(_registers) + - sizeof(_vectorScalarRegisters) == 1336, - "expected vector register offset to be 1336 bytes"); -} - -inline Registers_ppc64::Registers_ppc64() { - memset(&_registers, 0, sizeof(_registers)); - memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters)); -} - -inline bool Registers_ppc64::validRegister(int regNum) const { - switch (regNum) { - case UNW_REG_IP: - case UNW_REG_SP: - case UNW_PPC64_XER: - case UNW_PPC64_LR: - case UNW_PPC64_CTR: - case UNW_PPC64_VRSAVE: - return true; - } - - if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31) - return true; - if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7) - return true; - - return false; -} - -inline uint64_t Registers_ppc64::getRegister(int regNum) const { - switch (regNum) { - case UNW_REG_IP: - return _registers.__srr0; - case UNW_PPC64_R0: - return _registers.__r0; - case UNW_PPC64_R1: - case UNW_REG_SP: - return _registers.__r1; - case UNW_PPC64_R2: - return _registers.__r2; - case UNW_PPC64_R3: - return _registers.__r3; - case UNW_PPC64_R4: - return _registers.__r4; - case UNW_PPC64_R5: - return _registers.__r5; - case UNW_PPC64_R6: - return _registers.__r6; - case UNW_PPC64_R7: - return _registers.__r7; - case UNW_PPC64_R8: - return _registers.__r8; - case UNW_PPC64_R9: - return _registers.__r9; - case UNW_PPC64_R10: - return _registers.__r10; - case UNW_PPC64_R11: - return _registers.__r11; - case UNW_PPC64_R12: - return _registers.__r12; - case UNW_PPC64_R13: - return _registers.__r13; - case UNW_PPC64_R14: - return _registers.__r14; - case UNW_PPC64_R15: - return _registers.__r15; - case UNW_PPC64_R16: - return _registers.__r16; - case UNW_PPC64_R17: - return _registers.__r17; - case UNW_PPC64_R18: - return _registers.__r18; - case UNW_PPC64_R19: - return _registers.__r19; - case UNW_PPC64_R20: - return _registers.__r20; - case UNW_PPC64_R21: - return _registers.__r21; - case UNW_PPC64_R22: - return _registers.__r22; - case UNW_PPC64_R23: - return _registers.__r23; - case UNW_PPC64_R24: - return _registers.__r24; - case UNW_PPC64_R25: - return _registers.__r25; - case UNW_PPC64_R26: - return _registers.__r26; - case UNW_PPC64_R27: - return _registers.__r27; - case UNW_PPC64_R28: - return _registers.__r28; - case UNW_PPC64_R29: - return _registers.__r29; - case UNW_PPC64_R30: - return _registers.__r30; - case UNW_PPC64_R31: - return _registers.__r31; - case UNW_PPC64_CR0: - return (_registers.__cr & 0xF0000000); - case UNW_PPC64_CR1: - return (_registers.__cr & 0x0F000000); - case UNW_PPC64_CR2: - return (_registers.__cr & 0x00F00000); - case UNW_PPC64_CR3: - return (_registers.__cr & 0x000F0000); - case UNW_PPC64_CR4: - return (_registers.__cr & 0x0000F000); - case UNW_PPC64_CR5: - return (_registers.__cr & 0x00000F00); - case UNW_PPC64_CR6: - return (_registers.__cr & 0x000000F0); - case UNW_PPC64_CR7: - return (_registers.__cr & 0x0000000F); - case UNW_PPC64_XER: - return _registers.__xer; - case UNW_PPC64_LR: - return _registers.__lr; - case UNW_PPC64_CTR: - return _registers.__ctr; - case UNW_PPC64_VRSAVE: - return _registers.__vrsave; - } - _LIBUNWIND_ABORT("unsupported ppc64 register"); -} - -inline void Registers_ppc64::setRegister(int regNum, uint64_t value) { - switch (regNum) { - case UNW_REG_IP: - _registers.__srr0 = value; - return; - case UNW_PPC64_R0: - _registers.__r0 = value; - return; - case UNW_PPC64_R1: - case UNW_REG_SP: - _registers.__r1 = value; - return; - case UNW_PPC64_R2: - _registers.__r2 = value; - return; - case UNW_PPC64_R3: - _registers.__r3 = value; - return; - case UNW_PPC64_R4: - _registers.__r4 = value; - return; - case UNW_PPC64_R5: - _registers.__r5 = value; - return; - case UNW_PPC64_R6: - _registers.__r6 = value; - return; - case UNW_PPC64_R7: - _registers.__r7 = value; - return; - case UNW_PPC64_R8: - _registers.__r8 = value; - return; - case UNW_PPC64_R9: - _registers.__r9 = value; - return; - case UNW_PPC64_R10: - _registers.__r10 = value; - return; - case UNW_PPC64_R11: - _registers.__r11 = value; - return; - case UNW_PPC64_R12: - _registers.__r12 = value; - return; - case UNW_PPC64_R13: - _registers.__r13 = value; - return; - case UNW_PPC64_R14: - _registers.__r14 = value; - return; - case UNW_PPC64_R15: - _registers.__r15 = value; - return; - case UNW_PPC64_R16: - _registers.__r16 = value; - return; - case UNW_PPC64_R17: - _registers.__r17 = value; - return; - case UNW_PPC64_R18: - _registers.__r18 = value; - return; - case UNW_PPC64_R19: - _registers.__r19 = value; - return; - case UNW_PPC64_R20: - _registers.__r20 = value; - return; - case UNW_PPC64_R21: - _registers.__r21 = value; - return; - case UNW_PPC64_R22: - _registers.__r22 = value; - return; - case UNW_PPC64_R23: - _registers.__r23 = value; - return; - case UNW_PPC64_R24: - _registers.__r24 = value; - return; - case UNW_PPC64_R25: - _registers.__r25 = value; - return; - case UNW_PPC64_R26: - _registers.__r26 = value; - return; - case UNW_PPC64_R27: - _registers.__r27 = value; - return; - case UNW_PPC64_R28: - _registers.__r28 = value; - return; - case UNW_PPC64_R29: - _registers.__r29 = value; - return; - case UNW_PPC64_R30: - _registers.__r30 = value; - return; - case UNW_PPC64_R31: - _registers.__r31 = value; - return; - case UNW_PPC64_CR0: - _registers.__cr &= 0x0FFFFFFF; - _registers.__cr |= (value & 0xF0000000); - return; - case UNW_PPC64_CR1: - _registers.__cr &= 0xF0FFFFFF; - _registers.__cr |= (value & 0x0F000000); - return; - case UNW_PPC64_CR2: - _registers.__cr &= 0xFF0FFFFF; - _registers.__cr |= (value & 0x00F00000); - return; - case UNW_PPC64_CR3: - _registers.__cr &= 0xFFF0FFFF; - _registers.__cr |= (value & 0x000F0000); - return; - case UNW_PPC64_CR4: - _registers.__cr &= 0xFFFF0FFF; - _registers.__cr |= (value & 0x0000F000); - return; - case UNW_PPC64_CR5: - _registers.__cr &= 0xFFFFF0FF; - _registers.__cr |= (value & 0x00000F00); - return; - case UNW_PPC64_CR6: - _registers.__cr &= 0xFFFFFF0F; - _registers.__cr |= (value & 0x000000F0); - return; - case UNW_PPC64_CR7: - _registers.__cr &= 0xFFFFFFF0; - _registers.__cr |= (value & 0x0000000F); - return; - case UNW_PPC64_XER: - _registers.__xer = value; - return; - case UNW_PPC64_LR: - _registers.__lr = value; - return; - case UNW_PPC64_CTR: - _registers.__ctr = value; - return; - case UNW_PPC64_VRSAVE: - _registers.__vrsave = value; - return; - } - _LIBUNWIND_ABORT("unsupported ppc64 register"); -} - -inline bool Registers_ppc64::validFloatRegister(int regNum) const { - return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31; -} - -inline double Registers_ppc64::getFloatRegister(int regNum) const { - assert(validFloatRegister(regNum)); - return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f; -} - -inline void Registers_ppc64::setFloatRegister(int regNum, double value) { - assert(validFloatRegister(regNum)); - _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value; -} - -inline bool Registers_ppc64::validVectorRegister(int regNum) const { -#ifdef PPC64_HAS_VMX - if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31) - return true; - if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63) - return true; -#else - if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31) - return true; -#endif - return false; -} - -inline int Registers_ppc64::getVectorRegNum(int num) -{ - if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31) - return num - UNW_PPC64_VS0; - else - return num - UNW_PPC64_VS32 + 32; -} - -inline v128 Registers_ppc64::getVectorRegister(int regNum) const { - assert(validVectorRegister(regNum)); - return _vectorScalarRegisters[getVectorRegNum(regNum)].v; -} - -inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) { - assert(validVectorRegister(regNum)); - _vectorScalarRegisters[getVectorRegNum(regNum)].v = value; -} - -inline const char *Registers_ppc64::getRegisterName(int regNum) { - switch (regNum) { - case UNW_REG_IP: - return "ip"; - case UNW_REG_SP: - return "sp"; - case UNW_PPC64_R0: - return "r0"; - case UNW_PPC64_R1: - return "r1"; - case UNW_PPC64_R2: - return "r2"; - case UNW_PPC64_R3: - return "r3"; - case UNW_PPC64_R4: - return "r4"; - case UNW_PPC64_R5: - return "r5"; - case UNW_PPC64_R6: - return "r6"; - case UNW_PPC64_R7: - return "r7"; - case UNW_PPC64_R8: - return "r8"; - case UNW_PPC64_R9: - return "r9"; - case UNW_PPC64_R10: - return "r10"; - case UNW_PPC64_R11: - return "r11"; - case UNW_PPC64_R12: - return "r12"; - case UNW_PPC64_R13: - return "r13"; - case UNW_PPC64_R14: - return "r14"; - case UNW_PPC64_R15: - return "r15"; - case UNW_PPC64_R16: - return "r16"; - case UNW_PPC64_R17: - return "r17"; - case UNW_PPC64_R18: - return "r18"; - case UNW_PPC64_R19: - return "r19"; - case UNW_PPC64_R20: - return "r20"; - case UNW_PPC64_R21: - return "r21"; - case UNW_PPC64_R22: - return "r22"; - case UNW_PPC64_R23: - return "r23"; - case UNW_PPC64_R24: - return "r24"; - case UNW_PPC64_R25: - return "r25"; - case UNW_PPC64_R26: - return "r26"; - case UNW_PPC64_R27: - return "r27"; - case UNW_PPC64_R28: - return "r28"; - case UNW_PPC64_R29: - return "r29"; - case UNW_PPC64_R30: - return "r30"; - case UNW_PPC64_R31: - return "r31"; - case UNW_PPC64_CR0: - return "cr0"; - case UNW_PPC64_CR1: - return "cr1"; - case UNW_PPC64_CR2: - return "cr2"; - case UNW_PPC64_CR3: - return "cr3"; - case UNW_PPC64_CR4: - return "cr4"; - case UNW_PPC64_CR5: - return "cr5"; - case UNW_PPC64_CR6: - return "cr6"; - case UNW_PPC64_CR7: - return "cr7"; - case UNW_PPC64_XER: - return "xer"; - case UNW_PPC64_LR: - return "lr"; - case UNW_PPC64_CTR: - return "ctr"; - case UNW_PPC64_VRSAVE: - return "vrsave"; - case UNW_PPC64_F0: - return "fp0"; - case UNW_PPC64_F1: - return "fp1"; - case UNW_PPC64_F2: - return "fp2"; - case UNW_PPC64_F3: - return "fp3"; - case UNW_PPC64_F4: - return "fp4"; - case UNW_PPC64_F5: - return "fp5"; - case UNW_PPC64_F6: - return "fp6"; - case UNW_PPC64_F7: - return "fp7"; - case UNW_PPC64_F8: - return "fp8"; - case UNW_PPC64_F9: - return "fp9"; - case UNW_PPC64_F10: - return "fp10"; - case UNW_PPC64_F11: - return "fp11"; - case UNW_PPC64_F12: - return "fp12"; - case UNW_PPC64_F13: - return "fp13"; - case UNW_PPC64_F14: - return "fp14"; - case UNW_PPC64_F15: - return "fp15"; - case UNW_PPC64_F16: - return "fp16"; - case UNW_PPC64_F17: - return "fp17"; - case UNW_PPC64_F18: - return "fp18"; - case UNW_PPC64_F19: - return "fp19"; - case UNW_PPC64_F20: - return "fp20"; - case UNW_PPC64_F21: - return "fp21"; - case UNW_PPC64_F22: - return "fp22"; - case UNW_PPC64_F23: - return "fp23"; - case UNW_PPC64_F24: - return "fp24"; - case UNW_PPC64_F25: - return "fp25"; - case UNW_PPC64_F26: - return "fp26"; - case UNW_PPC64_F27: - return "fp27"; - case UNW_PPC64_F28: - return "fp28"; - case UNW_PPC64_F29: - return "fp29"; - case UNW_PPC64_F30: - return "fp30"; - case UNW_PPC64_F31: - return "fp31"; - case UNW_PPC64_V0: - return "v0"; - case UNW_PPC64_V1: - return "v1"; - case UNW_PPC64_V2: - return "v2"; - case UNW_PPC64_V3: - return "v3"; - case UNW_PPC64_V4: - return "v4"; - case UNW_PPC64_V5: - return "v5"; - case UNW_PPC64_V6: - return "v6"; - case UNW_PPC64_V7: - return "v7"; - case UNW_PPC64_V8: - return "v8"; - case UNW_PPC64_V9: - return "v9"; - case UNW_PPC64_V10: - return "v10"; - case UNW_PPC64_V11: - return "v11"; - case UNW_PPC64_V12: - return "v12"; - case UNW_PPC64_V13: - return "v13"; - case UNW_PPC64_V14: - return "v14"; - case UNW_PPC64_V15: - return "v15"; - case UNW_PPC64_V16: - return "v16"; - case UNW_PPC64_V17: - return "v17"; - case UNW_PPC64_V18: - return "v18"; - case UNW_PPC64_V19: - return "v19"; - case UNW_PPC64_V20: - return "v20"; - case UNW_PPC64_V21: - return "v21"; - case UNW_PPC64_V22: - return "v22"; - case UNW_PPC64_V23: - return "v23"; - case UNW_PPC64_V24: - return "v24"; - case UNW_PPC64_V25: - return "v25"; - case UNW_PPC64_V26: - return "v26"; - case UNW_PPC64_V27: - return "v27"; - case UNW_PPC64_V28: - return "v28"; - case UNW_PPC64_V29: - return "v29"; - case UNW_PPC64_V30: - return "v30"; - case UNW_PPC64_V31: - return "v31"; - } - return "unknown register"; -} -#endif // _LIBUNWIND_TARGET_PPC64 - - -#if defined(_LIBUNWIND_TARGET_AARCH64) -/// Registers_arm64 holds the register state of a thread in a 64-bit arm -/// process. -class _LIBUNWIND_HIDDEN Registers_arm64 { -public: - Registers_arm64(); - Registers_arm64(const void *registers); - - bool validRegister(int num) const; - uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); - bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); - bool validVectorRegister(int num) const; - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - static const char *getRegisterName(int num); - void jumpto(); - static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } - static int getArch() { return REGISTERS_ARM64; } - - uint64_t getSP() const { return _registers.__sp; } - void setSP(uint64_t value) { _registers.__sp = value; } - uint64_t getIP() const { return _registers.__pc; } - void setIP(uint64_t value) { _registers.__pc = value; } - uint64_t getFP() const { return _registers.__fp; } - void setFP(uint64_t value) { _registers.__fp = value; } - -private: - struct GPRs { - uint64_t __x[29]; // x0-x28 - uint64_t __fp; // Frame pointer x29 - uint64_t __lr; // Link register x30 - uint64_t __sp; // Stack pointer x31 - uint64_t __pc; // Program counter - uint64_t __ra_sign_state; // RA sign state register - }; - - GPRs _registers; - double _vectorHalfRegisters[32]; - // Currently only the lower double in 128-bit vectore registers - // is perserved during unwinding. We could define new register - // numbers (> 96) which mean whole vector registers, then this - // struct would need to change to contain whole vector registers. -}; - -inline Registers_arm64::Registers_arm64(const void *registers) { - static_assert((check_fit::does_fit), - "arm64 registers do not fit into unw_context_t"); - memcpy(&_registers, registers, sizeof(_registers)); - static_assert(sizeof(GPRs) == 0x110, - "expected VFP registers to be at offset 272"); - memcpy(_vectorHalfRegisters, - static_cast(registers) + sizeof(GPRs), - sizeof(_vectorHalfRegisters)); -} - -inline Registers_arm64::Registers_arm64() { - memset(&_registers, 0, sizeof(_registers)); - memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters)); -} - -inline bool Registers_arm64::validRegister(int regNum) const { - if (regNum == UNW_REG_IP) - return true; - if (regNum == UNW_REG_SP) - return true; - if (regNum < 0) - return false; - if (regNum > 95) - return false; - if (regNum == UNW_ARM64_RA_SIGN_STATE) - return true; - if ((regNum > 31) && (regNum < 64)) - return false; - return true; -} - -inline uint64_t Registers_arm64::getRegister(int regNum) const { - if (regNum == UNW_REG_IP) - return _registers.__pc; - if (regNum == UNW_REG_SP) - return _registers.__sp; - if (regNum == UNW_ARM64_RA_SIGN_STATE) - return _registers.__ra_sign_state; - if ((regNum >= 0) && (regNum < 32)) - return _registers.__x[regNum]; - _LIBUNWIND_ABORT("unsupported arm64 register"); -} - -inline void Registers_arm64::setRegister(int regNum, uint64_t value) { - if (regNum == UNW_REG_IP) - _registers.__pc = value; - else if (regNum == UNW_REG_SP) - _registers.__sp = value; - else if (regNum == UNW_ARM64_RA_SIGN_STATE) - _registers.__ra_sign_state = value; - else if ((regNum >= 0) && (regNum < 32)) - _registers.__x[regNum] = value; - else - _LIBUNWIND_ABORT("unsupported arm64 register"); -} - -inline const char *Registers_arm64::getRegisterName(int regNum) { - switch (regNum) { - case UNW_REG_IP: - return "pc"; - case UNW_REG_SP: - return "sp"; - case UNW_ARM64_X0: - return "x0"; - case UNW_ARM64_X1: - return "x1"; - case UNW_ARM64_X2: - return "x2"; - case UNW_ARM64_X3: - return "x3"; - case UNW_ARM64_X4: - return "x4"; - case UNW_ARM64_X5: - return "x5"; - case UNW_ARM64_X6: - return "x6"; - case UNW_ARM64_X7: - return "x7"; - case UNW_ARM64_X8: - return "x8"; - case UNW_ARM64_X9: - return "x9"; - case UNW_ARM64_X10: - return "x10"; - case UNW_ARM64_X11: - return "x11"; - case UNW_ARM64_X12: - return "x12"; - case UNW_ARM64_X13: - return "x13"; - case UNW_ARM64_X14: - return "x14"; - case UNW_ARM64_X15: - return "x15"; - case UNW_ARM64_X16: - return "x16"; - case UNW_ARM64_X17: - return "x17"; - case UNW_ARM64_X18: - return "x18"; - case UNW_ARM64_X19: - return "x19"; - case UNW_ARM64_X20: - return "x20"; - case UNW_ARM64_X21: - return "x21"; - case UNW_ARM64_X22: - return "x22"; - case UNW_ARM64_X23: - return "x23"; - case UNW_ARM64_X24: - return "x24"; - case UNW_ARM64_X25: - return "x25"; - case UNW_ARM64_X26: - return "x26"; - case UNW_ARM64_X27: - return "x27"; - case UNW_ARM64_X28: - return "x28"; - case UNW_ARM64_X29: - return "fp"; - case UNW_ARM64_X30: - return "lr"; - case UNW_ARM64_X31: - return "sp"; - case UNW_ARM64_D0: - return "d0"; - case UNW_ARM64_D1: - return "d1"; - case UNW_ARM64_D2: - return "d2"; - case UNW_ARM64_D3: - return "d3"; - case UNW_ARM64_D4: - return "d4"; - case UNW_ARM64_D5: - return "d5"; - case UNW_ARM64_D6: - return "d6"; - case UNW_ARM64_D7: - return "d7"; - case UNW_ARM64_D8: - return "d8"; - case UNW_ARM64_D9: - return "d9"; - case UNW_ARM64_D10: - return "d10"; - case UNW_ARM64_D11: - return "d11"; - case UNW_ARM64_D12: - return "d12"; - case UNW_ARM64_D13: - return "d13"; - case UNW_ARM64_D14: - return "d14"; - case UNW_ARM64_D15: - return "d15"; - case UNW_ARM64_D16: - return "d16"; - case UNW_ARM64_D17: - return "d17"; - case UNW_ARM64_D18: - return "d18"; - case UNW_ARM64_D19: - return "d19"; - case UNW_ARM64_D20: - return "d20"; - case UNW_ARM64_D21: - return "d21"; - case UNW_ARM64_D22: - return "d22"; - case UNW_ARM64_D23: - return "d23"; - case UNW_ARM64_D24: - return "d24"; - case UNW_ARM64_D25: - return "d25"; - case UNW_ARM64_D26: - return "d26"; - case UNW_ARM64_D27: - return "d27"; - case UNW_ARM64_D28: - return "d28"; - case UNW_ARM64_D29: - return "d29"; - case UNW_ARM64_D30: - return "d30"; - case UNW_ARM64_D31: - return "d31"; - default: - return "unknown register"; - } -} - -inline bool Registers_arm64::validFloatRegister(int regNum) const { - if (regNum < UNW_ARM64_D0) - return false; - if (regNum > UNW_ARM64_D31) - return false; - return true; -} - -inline double Registers_arm64::getFloatRegister(int regNum) const { - assert(validFloatRegister(regNum)); - return _vectorHalfRegisters[regNum - UNW_ARM64_D0]; -} - -inline void Registers_arm64::setFloatRegister(int regNum, double value) { - assert(validFloatRegister(regNum)); - _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value; -} - -inline bool Registers_arm64::validVectorRegister(int) const { - return false; -} - -inline v128 Registers_arm64::getVectorRegister(int) const { - _LIBUNWIND_ABORT("no arm64 vector register support yet"); -} - -inline void Registers_arm64::setVectorRegister(int, v128) { - _LIBUNWIND_ABORT("no arm64 vector register support yet"); -} -#endif // _LIBUNWIND_TARGET_AARCH64 - -#if defined(_LIBUNWIND_TARGET_ARM) -/// Registers_arm holds the register state of a thread in a 32-bit arm -/// process. -/// -/// NOTE: Assumes VFPv3. On ARM processors without a floating point unit, -/// this uses more memory than required. -class _LIBUNWIND_HIDDEN Registers_arm { -public: - Registers_arm(); - Registers_arm(const void *registers); - - bool validRegister(int num) const; - uint32_t getRegister(int num) const; - void setRegister(int num, uint32_t value); - bool validFloatRegister(int num) const; - unw_fpreg_t getFloatRegister(int num); - void setFloatRegister(int num, unw_fpreg_t value); - bool validVectorRegister(int num) const; - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - static const char *getRegisterName(int num); - void jumpto() { - restoreSavedFloatRegisters(); - restoreCoreAndJumpTo(); - } - static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; } - static int getArch() { return REGISTERS_ARM; } - - uint32_t getSP() const { return _registers.__sp; } - void setSP(uint32_t value) { _registers.__sp = value; } - uint32_t getIP() const { return _registers.__pc; } - void setIP(uint32_t value) { _registers.__pc = value; } - - void saveVFPAsX() { - assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15); - _use_X_for_vfp_save = true; - } - - void restoreSavedFloatRegisters() { - if (_saved_vfp_d0_d15) { - if (_use_X_for_vfp_save) - restoreVFPWithFLDMX(_vfp_d0_d15_pad); - else - restoreVFPWithFLDMD(_vfp_d0_d15_pad); - } - if (_saved_vfp_d16_d31) - restoreVFPv3(_vfp_d16_d31); -#if defined(__ARM_WMMX) - if (_saved_iwmmx) - restoreiWMMX(_iwmmx); - if (_saved_iwmmx_control) - restoreiWMMXControl(_iwmmx_control); -#endif - } - -private: - struct GPRs { - uint32_t __r[13]; // r0-r12 - uint32_t __sp; // Stack pointer r13 - uint32_t __lr; // Link register r14 - uint32_t __pc; // Program counter r15 - }; - - static void saveVFPWithFSTMD(unw_fpreg_t*); - static void saveVFPWithFSTMX(unw_fpreg_t*); - static void saveVFPv3(unw_fpreg_t*); - static void restoreVFPWithFLDMD(unw_fpreg_t*); - static void restoreVFPWithFLDMX(unw_fpreg_t*); - static void restoreVFPv3(unw_fpreg_t*); -#if defined(__ARM_WMMX) - static void saveiWMMX(unw_fpreg_t*); - static void saveiWMMXControl(uint32_t*); - static void restoreiWMMX(unw_fpreg_t*); - static void restoreiWMMXControl(uint32_t*); -#endif - void restoreCoreAndJumpTo(); - - // ARM registers - GPRs _registers; - - // We save floating point registers lazily because we can't know ahead of - // time which ones are used. See EHABI #4.7. - - // Whether D0-D15 are saved in the FTSMX instead of FSTMD format. - // - // See EHABI #7.5 that explains how matching instruction sequences for load - // and store need to be used to correctly restore the exact register bits. - bool _use_X_for_vfp_save; - // Whether VFP D0-D15 are saved. - bool _saved_vfp_d0_d15; - // Whether VFPv3 D16-D31 are saved. - bool _saved_vfp_d16_d31; - // VFP registers D0-D15, + padding if saved using FSTMX - unw_fpreg_t _vfp_d0_d15_pad[17]; - // VFPv3 registers D16-D31, always saved using FSTMD - unw_fpreg_t _vfp_d16_d31[16]; -#if defined(__ARM_WMMX) - // Whether iWMMX data registers are saved. - bool _saved_iwmmx; - // Whether iWMMX control registers are saved. - mutable bool _saved_iwmmx_control; - // iWMMX registers - unw_fpreg_t _iwmmx[16]; - // iWMMX control registers - mutable uint32_t _iwmmx_control[4]; -#endif -}; - -inline Registers_arm::Registers_arm(const void *registers) - : _use_X_for_vfp_save(false), - _saved_vfp_d0_d15(false), - _saved_vfp_d16_d31(false) { - static_assert((check_fit::does_fit), - "arm registers do not fit into unw_context_t"); - // See unw_getcontext() note about data. - memcpy(&_registers, registers, sizeof(_registers)); - memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); - memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); -#if defined(__ARM_WMMX) - _saved_iwmmx = false; - _saved_iwmmx_control = false; - memset(&_iwmmx, 0, sizeof(_iwmmx)); - memset(&_iwmmx_control, 0, sizeof(_iwmmx_control)); -#endif -} - -inline Registers_arm::Registers_arm() - : _use_X_for_vfp_save(false), - _saved_vfp_d0_d15(false), - _saved_vfp_d16_d31(false) { - memset(&_registers, 0, sizeof(_registers)); - memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); - memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); -#if defined(__ARM_WMMX) - _saved_iwmmx = false; - _saved_iwmmx_control = false; - memset(&_iwmmx, 0, sizeof(_iwmmx)); - memset(&_iwmmx_control, 0, sizeof(_iwmmx_control)); -#endif -} - -inline bool Registers_arm::validRegister(int regNum) const { - // Returns true for all non-VFP registers supported by the EHABI - // virtual register set (VRS). - if (regNum == UNW_REG_IP) - return true; - - if (regNum == UNW_REG_SP) - return true; - - if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) - return true; - -#if defined(__ARM_WMMX) - if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) - return true; -#endif - - return false; -} - -inline uint32_t Registers_arm::getRegister(int regNum) const { - if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) - return _registers.__sp; - - if (regNum == UNW_ARM_LR) - return _registers.__lr; - - if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) - return _registers.__pc; - - if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) - return _registers.__r[regNum]; - -#if defined(__ARM_WMMX) - if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) { - if (!_saved_iwmmx_control) { - _saved_iwmmx_control = true; - saveiWMMXControl(_iwmmx_control); - } - return _iwmmx_control[regNum - UNW_ARM_WC0]; - } -#endif - - _LIBUNWIND_ABORT("unsupported arm register"); -} - -inline void Registers_arm::setRegister(int regNum, uint32_t value) { - if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) { - _registers.__sp = value; - return; - } - - if (regNum == UNW_ARM_LR) { - _registers.__lr = value; - return; - } - - if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) { - _registers.__pc = value; - return; - } - - if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) { - _registers.__r[regNum] = value; - return; - } - -#if defined(__ARM_WMMX) - if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) { - if (!_saved_iwmmx_control) { - _saved_iwmmx_control = true; - saveiWMMXControl(_iwmmx_control); - } - _iwmmx_control[regNum - UNW_ARM_WC0] = value; - return; - } -#endif - - _LIBUNWIND_ABORT("unsupported arm register"); -} - -inline const char *Registers_arm::getRegisterName(int regNum) { - switch (regNum) { - case UNW_REG_IP: - case UNW_ARM_IP: // UNW_ARM_R15 is alias - return "pc"; - case UNW_ARM_LR: // UNW_ARM_R14 is alias - return "lr"; - case UNW_REG_SP: - case UNW_ARM_SP: // UNW_ARM_R13 is alias - return "sp"; - case UNW_ARM_R0: - return "r0"; - case UNW_ARM_R1: - return "r1"; - case UNW_ARM_R2: - return "r2"; - case UNW_ARM_R3: - return "r3"; - case UNW_ARM_R4: - return "r4"; - case UNW_ARM_R5: - return "r5"; - case UNW_ARM_R6: - return "r6"; - case UNW_ARM_R7: - return "r7"; - case UNW_ARM_R8: - return "r8"; - case UNW_ARM_R9: - return "r9"; - case UNW_ARM_R10: - return "r10"; - case UNW_ARM_R11: - return "r11"; - case UNW_ARM_R12: - return "r12"; - case UNW_ARM_S0: - return "s0"; - case UNW_ARM_S1: - return "s1"; - case UNW_ARM_S2: - return "s2"; - case UNW_ARM_S3: - return "s3"; - case UNW_ARM_S4: - return "s4"; - case UNW_ARM_S5: - return "s5"; - case UNW_ARM_S6: - return "s6"; - case UNW_ARM_S7: - return "s7"; - case UNW_ARM_S8: - return "s8"; - case UNW_ARM_S9: - return "s9"; - case UNW_ARM_S10: - return "s10"; - case UNW_ARM_S11: - return "s11"; - case UNW_ARM_S12: - return "s12"; - case UNW_ARM_S13: - return "s13"; - case UNW_ARM_S14: - return "s14"; - case UNW_ARM_S15: - return "s15"; - case UNW_ARM_S16: - return "s16"; - case UNW_ARM_S17: - return "s17"; - case UNW_ARM_S18: - return "s18"; - case UNW_ARM_S19: - return "s19"; - case UNW_ARM_S20: - return "s20"; - case UNW_ARM_S21: - return "s21"; - case UNW_ARM_S22: - return "s22"; - case UNW_ARM_S23: - return "s23"; - case UNW_ARM_S24: - return "s24"; - case UNW_ARM_S25: - return "s25"; - case UNW_ARM_S26: - return "s26"; - case UNW_ARM_S27: - return "s27"; - case UNW_ARM_S28: - return "s28"; - case UNW_ARM_S29: - return "s29"; - case UNW_ARM_S30: - return "s30"; - case UNW_ARM_S31: - return "s31"; - case UNW_ARM_D0: - return "d0"; - case UNW_ARM_D1: - return "d1"; - case UNW_ARM_D2: - return "d2"; - case UNW_ARM_D3: - return "d3"; - case UNW_ARM_D4: - return "d4"; - case UNW_ARM_D5: - return "d5"; - case UNW_ARM_D6: - return "d6"; - case UNW_ARM_D7: - return "d7"; - case UNW_ARM_D8: - return "d8"; - case UNW_ARM_D9: - return "d9"; - case UNW_ARM_D10: - return "d10"; - case UNW_ARM_D11: - return "d11"; - case UNW_ARM_D12: - return "d12"; - case UNW_ARM_D13: - return "d13"; - case UNW_ARM_D14: - return "d14"; - case UNW_ARM_D15: - return "d15"; - case UNW_ARM_D16: - return "d16"; - case UNW_ARM_D17: - return "d17"; - case UNW_ARM_D18: - return "d18"; - case UNW_ARM_D19: - return "d19"; - case UNW_ARM_D20: - return "d20"; - case UNW_ARM_D21: - return "d21"; - case UNW_ARM_D22: - return "d22"; - case UNW_ARM_D23: - return "d23"; - case UNW_ARM_D24: - return "d24"; - case UNW_ARM_D25: - return "d25"; - case UNW_ARM_D26: - return "d26"; - case UNW_ARM_D27: - return "d27"; - case UNW_ARM_D28: - return "d28"; - case UNW_ARM_D29: - return "d29"; - case UNW_ARM_D30: - return "d30"; - case UNW_ARM_D31: - return "d31"; - default: - return "unknown register"; - } -} - -inline bool Registers_arm::validFloatRegister(int regNum) const { - // NOTE: Consider the intel MMX registers floating points so the - // unw_get_fpreg can be used to transmit the 64-bit data back. - return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31)) -#if defined(__ARM_WMMX) - || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15)) -#endif - ; -} - -inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) { - if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) { - if (!_saved_vfp_d0_d15) { - _saved_vfp_d0_d15 = true; - if (_use_X_for_vfp_save) - saveVFPWithFSTMX(_vfp_d0_d15_pad); - else - saveVFPWithFSTMD(_vfp_d0_d15_pad); - } - return _vfp_d0_d15_pad[regNum - UNW_ARM_D0]; - } - - if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) { - if (!_saved_vfp_d16_d31) { - _saved_vfp_d16_d31 = true; - saveVFPv3(_vfp_d16_d31); - } - return _vfp_d16_d31[regNum - UNW_ARM_D16]; - } - -#if defined(__ARM_WMMX) - if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) { - if (!_saved_iwmmx) { - _saved_iwmmx = true; - saveiWMMX(_iwmmx); - } - return _iwmmx[regNum - UNW_ARM_WR0]; - } -#endif - - _LIBUNWIND_ABORT("Unknown ARM float register"); -} - -inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) { - if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) { - if (!_saved_vfp_d0_d15) { - _saved_vfp_d0_d15 = true; - if (_use_X_for_vfp_save) - saveVFPWithFSTMX(_vfp_d0_d15_pad); - else - saveVFPWithFSTMD(_vfp_d0_d15_pad); - } - _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value; - return; - } - - if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) { - if (!_saved_vfp_d16_d31) { - _saved_vfp_d16_d31 = true; - saveVFPv3(_vfp_d16_d31); - } - _vfp_d16_d31[regNum - UNW_ARM_D16] = value; - return; - } - -#if defined(__ARM_WMMX) - if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) { - if (!_saved_iwmmx) { - _saved_iwmmx = true; - saveiWMMX(_iwmmx); - } - _iwmmx[regNum - UNW_ARM_WR0] = value; - return; - } -#endif - - _LIBUNWIND_ABORT("Unknown ARM float register"); -} - -inline bool Registers_arm::validVectorRegister(int) const { - return false; -} - -inline v128 Registers_arm::getVectorRegister(int) const { - _LIBUNWIND_ABORT("ARM vector support not implemented"); -} - -inline void Registers_arm::setVectorRegister(int, v128) { - _LIBUNWIND_ABORT("ARM vector support not implemented"); -} -#endif // _LIBUNWIND_TARGET_ARM - - -#if defined(_LIBUNWIND_TARGET_OR1K) -/// Registers_or1k holds the register state of a thread in an OpenRISC1000 -/// process. -class _LIBUNWIND_HIDDEN Registers_or1k { -public: - Registers_or1k(); - Registers_or1k(const void *registers); - - bool validRegister(int num) const; - uint32_t getRegister(int num) const; - void setRegister(int num, uint32_t value); - bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); - bool validVectorRegister(int num) const; - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - static const char *getRegisterName(int num); - void jumpto(); - static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; } - static int getArch() { return REGISTERS_OR1K; } - - uint64_t getSP() const { return _registers.__r[1]; } - void setSP(uint32_t value) { _registers.__r[1] = value; } - uint64_t getIP() const { return _registers.__pc; } - void setIP(uint32_t value) { _registers.__pc = value; } - -private: - struct or1k_thread_state_t { - unsigned int __r[32]; // r0-r31 - unsigned int __pc; // Program counter - unsigned int __epcr; // Program counter at exception - }; - - or1k_thread_state_t _registers; -}; - -inline Registers_or1k::Registers_or1k(const void *registers) { - static_assert((check_fit::does_fit), - "or1k registers do not fit into unw_context_t"); - memcpy(&_registers, static_cast(registers), - sizeof(_registers)); -} - -inline Registers_or1k::Registers_or1k() { - memset(&_registers, 0, sizeof(_registers)); -} - -inline bool Registers_or1k::validRegister(int regNum) const { - if (regNum == UNW_REG_IP) - return true; - if (regNum == UNW_REG_SP) - return true; - if (regNum < 0) - return false; - if (regNum <= UNW_OR1K_R31) - return true; - if (regNum == UNW_OR1K_EPCR) - return true; - return false; -} - -inline uint32_t Registers_or1k::getRegister(int regNum) const { - if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) - return _registers.__r[regNum - UNW_OR1K_R0]; - - switch (regNum) { - case UNW_REG_IP: - return _registers.__pc; - case UNW_REG_SP: - return _registers.__r[1]; - case UNW_OR1K_EPCR: - return _registers.__epcr; - } - _LIBUNWIND_ABORT("unsupported or1k register"); -} - -inline void Registers_or1k::setRegister(int regNum, uint32_t value) { - if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) { - _registers.__r[regNum - UNW_OR1K_R0] = value; - return; - } - - switch (regNum) { - case UNW_REG_IP: - _registers.__pc = value; - return; - case UNW_REG_SP: - _registers.__r[1] = value; - return; - case UNW_OR1K_EPCR: - _registers.__epcr = value; - return; - } - _LIBUNWIND_ABORT("unsupported or1k register"); -} - -inline bool Registers_or1k::validFloatRegister(int /* regNum */) const { - return false; -} - -inline double Registers_or1k::getFloatRegister(int /* regNum */) const { - _LIBUNWIND_ABORT("or1k float support not implemented"); -} - -inline void Registers_or1k::setFloatRegister(int /* regNum */, - double /* value */) { - _LIBUNWIND_ABORT("or1k float support not implemented"); -} - -inline bool Registers_or1k::validVectorRegister(int /* regNum */) const { - return false; -} - -inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const { - _LIBUNWIND_ABORT("or1k vector support not implemented"); -} - -inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) { - _LIBUNWIND_ABORT("or1k vector support not implemented"); -} - -inline const char *Registers_or1k::getRegisterName(int regNum) { - switch (regNum) { - case UNW_OR1K_R0: - return "r0"; - case UNW_OR1K_R1: - return "r1"; - case UNW_OR1K_R2: - return "r2"; - case UNW_OR1K_R3: - return "r3"; - case UNW_OR1K_R4: - return "r4"; - case UNW_OR1K_R5: - return "r5"; - case UNW_OR1K_R6: - return "r6"; - case UNW_OR1K_R7: - return "r7"; - case UNW_OR1K_R8: - return "r8"; - case UNW_OR1K_R9: - return "r9"; - case UNW_OR1K_R10: - return "r10"; - case UNW_OR1K_R11: - return "r11"; - case UNW_OR1K_R12: - return "r12"; - case UNW_OR1K_R13: - return "r13"; - case UNW_OR1K_R14: - return "r14"; - case UNW_OR1K_R15: - return "r15"; - case UNW_OR1K_R16: - return "r16"; - case UNW_OR1K_R17: - return "r17"; - case UNW_OR1K_R18: - return "r18"; - case UNW_OR1K_R19: - return "r19"; - case UNW_OR1K_R20: - return "r20"; - case UNW_OR1K_R21: - return "r21"; - case UNW_OR1K_R22: - return "r22"; - case UNW_OR1K_R23: - return "r23"; - case UNW_OR1K_R24: - return "r24"; - case UNW_OR1K_R25: - return "r25"; - case UNW_OR1K_R26: - return "r26"; - case UNW_OR1K_R27: - return "r27"; - case UNW_OR1K_R28: - return "r28"; - case UNW_OR1K_R29: - return "r29"; - case UNW_OR1K_R30: - return "r30"; - case UNW_OR1K_R31: - return "r31"; - case UNW_OR1K_EPCR: - return "EPCR"; - default: - return "unknown register"; - } - -} -#endif // _LIBUNWIND_TARGET_OR1K - -#if defined(_LIBUNWIND_TARGET_RISCV) -/// Registers_riscv holds the register state of a thread in a 64-bit RISC-V -/// process. -class _LIBUNWIND_HIDDEN Registers_riscv { -public: - Registers_riscv(); - Registers_riscv(const void *registers); - - bool validRegister(int num) const; - uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); - bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); - bool validVectorRegister(int num) const; - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - static const char *getRegisterName(int num); - void jumpto(); - static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; } - static int getArch() { return REGISTERS_RISCV; } - - uint64_t getSP() const { return _registers.__x[2]; } - void setSP(uint64_t value) { _registers.__x[2] = value; } - uint64_t getIP() const { return _registers.__x[1]; } - void setIP(uint64_t value) { _registers.__x[1] = value; } - -private: - struct GPRs { - uint64_t __x[32]; // x0-x31 - }; - - GPRs _registers; - double _vectorHalfRegisters[32]; - // Currently only the lower double in 128-bit vectore registers - // is perserved during unwinding. We could define new register - // numbers (> 96) which mean whole vector registers, then this - // struct would need to change to contain whole vector registers. -}; - -inline Registers_riscv::Registers_riscv(const void *registers) { - static_assert((check_fit::does_fit), - "riscv registers do not fit into unw_context_t"); - memcpy(&_registers, registers, sizeof(_registers)); - static_assert(sizeof(GPRs) == 0x100, - "expected VFP registers to be at offset 256"); - memcpy(_vectorHalfRegisters, - static_cast(registers) + sizeof(GPRs), - sizeof(_vectorHalfRegisters)); -} - -inline Registers_riscv::Registers_riscv() { - memset(&_registers, 0, sizeof(_registers)); - memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters)); -} - -inline bool Registers_riscv::validRegister(int regNum) const { - if (regNum == UNW_REG_IP) - return true; - if (regNum == UNW_REG_SP) - return true; - if (regNum < 0) - return false; - if (regNum > 95) - return false; - if ((regNum > 31) && (regNum < 64)) - return false; - return true; -} - -inline uint64_t Registers_riscv::getRegister(int regNum) const { - if (regNum == UNW_REG_IP) - return _registers.__x[1]; - if (regNum == UNW_REG_SP) - return _registers.__x[2]; - if ((regNum >= 0) && (regNum < 32)) - return _registers.__x[regNum]; - _LIBUNWIND_ABORT("unsupported riscv register"); -} - -inline void Registers_riscv::setRegister(int regNum, uint64_t value) { - if (regNum == UNW_REG_IP) - _registers.__x[1] = value; - else if (regNum == UNW_REG_SP) - _registers.__x[2] = value; - else if ((regNum >= 0) && (regNum < 32)) - _registers.__x[regNum] = value; - else - _LIBUNWIND_ABORT("unsupported riscv register"); -} - -inline const char *Registers_riscv::getRegisterName(int regNum) { - switch (regNum) { - case UNW_REG_IP: - return "ra"; - case UNW_REG_SP: - return "sp"; - case UNW_RISCV_X0: - return "x0"; - case UNW_RISCV_X1: - return "ra"; - case UNW_RISCV_X2: - return "sp"; - case UNW_RISCV_X3: - return "x3"; - case UNW_RISCV_X4: - return "x4"; - case UNW_RISCV_X5: - return "x5"; - case UNW_RISCV_X6: - return "x6"; - case UNW_RISCV_X7: - return "x7"; - case UNW_RISCV_X8: - return "x8"; - case UNW_RISCV_X9: - return "x9"; - case UNW_RISCV_X10: - return "x10"; - case UNW_RISCV_X11: - return "x11"; - case UNW_RISCV_X12: - return "x12"; - case UNW_RISCV_X13: - return "x13"; - case UNW_RISCV_X14: - return "x14"; - case UNW_RISCV_X15: - return "x15"; - case UNW_RISCV_X16: - return "x16"; - case UNW_RISCV_X17: - return "x17"; - case UNW_RISCV_X18: - return "x18"; - case UNW_RISCV_X19: - return "x19"; - case UNW_RISCV_X20: - return "x20"; - case UNW_RISCV_X21: - return "x21"; - case UNW_RISCV_X22: - return "x22"; - case UNW_RISCV_X23: - return "x23"; - case UNW_RISCV_X24: - return "x24"; - case UNW_RISCV_X25: - return "x25"; - case UNW_RISCV_X26: - return "x26"; - case UNW_RISCV_X27: - return "x27"; - case UNW_RISCV_X28: - return "x28"; - case UNW_RISCV_X29: - return "x29"; - case UNW_RISCV_X30: - return "x30"; - case UNW_RISCV_X31: - return "x31"; - case UNW_RISCV_D0: - return "d0"; - case UNW_RISCV_D1: - return "d1"; - case UNW_RISCV_D2: - return "d2"; - case UNW_RISCV_D3: - return "d3"; - case UNW_RISCV_D4: - return "d4"; - case UNW_RISCV_D5: - return "d5"; - case UNW_RISCV_D6: - return "d6"; - case UNW_RISCV_D7: - return "d7"; - case UNW_RISCV_D8: - return "d8"; - case UNW_RISCV_D9: - return "d9"; - case UNW_RISCV_D10: - return "d10"; - case UNW_RISCV_D11: - return "d11"; - case UNW_RISCV_D12: - return "d12"; - case UNW_RISCV_D13: - return "d13"; - case UNW_RISCV_D14: - return "d14"; - case UNW_RISCV_D15: - return "d15"; - case UNW_RISCV_D16: - return "d16"; - case UNW_RISCV_D17: - return "d17"; - case UNW_RISCV_D18: - return "d18"; - case UNW_RISCV_D19: - return "d19"; - case UNW_RISCV_D20: - return "d20"; - case UNW_RISCV_D21: - return "d21"; - case UNW_RISCV_D22: - return "d22"; - case UNW_RISCV_D23: - return "d23"; - case UNW_RISCV_D24: - return "d24"; - case UNW_RISCV_D25: - return "d25"; - case UNW_RISCV_D26: - return "d26"; - case UNW_RISCV_D27: - return "d27"; - case UNW_RISCV_D28: - return "d28"; - case UNW_RISCV_D29: - return "d29"; - case UNW_RISCV_D30: - return "d30"; - case UNW_RISCV_D31: - return "d31"; - default: - return "unknown register"; - } -} - -inline bool Registers_riscv::validFloatRegister(int regNum) const { - if (regNum < UNW_RISCV_D0) - return false; - if (regNum > UNW_RISCV_D31) - return false; - return true; -} - -inline double Registers_riscv::getFloatRegister(int regNum) const { - assert(validFloatRegister(regNum)); - return _vectorHalfRegisters[regNum - UNW_RISCV_D0]; -} - -inline void Registers_riscv::setFloatRegister(int regNum, double value) { - assert(validFloatRegister(regNum)); - _vectorHalfRegisters[regNum - UNW_RISCV_D0] = value; -} - -inline bool Registers_riscv::validVectorRegister(int) const { - return false; -} - -inline v128 Registers_riscv::getVectorRegister(int) const { - _LIBUNWIND_ABORT("no riscv vector register support yet"); -} - -inline void Registers_riscv::setVectorRegister(int, v128) { - _LIBUNWIND_ABORT("no riscv vector register support yet"); -} -#endif // _LIBUNWIND_TARGET_RISCV - -#if defined(_LIBUNWIND_TARGET_MIPS_O32) -/// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS -/// process. -class _LIBUNWIND_HIDDEN Registers_mips_o32 { -public: - Registers_mips_o32(); - Registers_mips_o32(const void *registers); - - bool validRegister(int num) const; - uint32_t getRegister(int num) const; - void setRegister(int num, uint32_t value); - bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); - bool validVectorRegister(int num) const; - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - static const char *getRegisterName(int num); - void jumpto(); - static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } - static int getArch() { return REGISTERS_MIPS_O32; } - - uint32_t getSP() const { return _registers.__r[29]; } - void setSP(uint32_t value) { _registers.__r[29] = value; } - uint32_t getIP() const { return _registers.__pc; } - void setIP(uint32_t value) { _registers.__pc = value; } - -private: - struct mips_o32_thread_state_t { - uint32_t __r[32]; - uint32_t __pc; - uint32_t __hi; - uint32_t __lo; - }; - - mips_o32_thread_state_t _registers; -#ifdef __mips_hard_float - /// O32 with 32-bit floating point registers only uses half of this - /// space. However, using the same layout for 32-bit vs 64-bit - /// floating point registers results in a single context size for - /// O32 with hard float. - uint32_t _padding; - double _floats[32]; -#endif -}; - -inline Registers_mips_o32::Registers_mips_o32(const void *registers) { - static_assert((check_fit::does_fit), - "mips_o32 registers do not fit into unw_context_t"); - memcpy(&_registers, static_cast(registers), - sizeof(_registers)); -} - -inline Registers_mips_o32::Registers_mips_o32() { - memset(&_registers, 0, sizeof(_registers)); -} - -inline bool Registers_mips_o32::validRegister(int regNum) const { - if (regNum == UNW_REG_IP) - return true; - if (regNum == UNW_REG_SP) - return true; - if (regNum < 0) - return false; - if (regNum <= UNW_MIPS_R31) - return true; -#if __mips_isa_rev != 6 - if (regNum == UNW_MIPS_HI) - return true; - if (regNum == UNW_MIPS_LO) - return true; -#endif -#if defined(__mips_hard_float) && __mips_fpr == 32 - if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) - return true; -#endif - // FIXME: DSP accumulator registers, MSA registers - return false; -} - -inline uint32_t Registers_mips_o32::getRegister(int regNum) const { - if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) - return _registers.__r[regNum - UNW_MIPS_R0]; -#if defined(__mips_hard_float) && __mips_fpr == 32 - if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) { - uint32_t *p; - - if (regNum % 2 == 0) - p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0]; - else - p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1; - return *p; - } -#endif - - switch (regNum) { - case UNW_REG_IP: - return _registers.__pc; - case UNW_REG_SP: - return _registers.__r[29]; - case UNW_MIPS_HI: - return _registers.__hi; - case UNW_MIPS_LO: - return _registers.__lo; - } - _LIBUNWIND_ABORT("unsupported mips_o32 register"); -} - -inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) { - if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) { - _registers.__r[regNum - UNW_MIPS_R0] = value; - return; - } -#if defined(__mips_hard_float) && __mips_fpr == 32 - if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) { - uint32_t *p; - - if (regNum % 2 == 0) - p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0]; - else - p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1; - *p = value; - return; - } -#endif - - switch (regNum) { - case UNW_REG_IP: - _registers.__pc = value; - return; - case UNW_REG_SP: - _registers.__r[29] = value; - return; - case UNW_MIPS_HI: - _registers.__hi = value; - return; - case UNW_MIPS_LO: - _registers.__lo = value; - return; - } - _LIBUNWIND_ABORT("unsupported mips_o32 register"); -} - -inline bool Registers_mips_o32::validFloatRegister(int regNum) const { -#if defined(__mips_hard_float) && __mips_fpr == 64 - if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) - return true; -#endif - return false; -} - -inline double Registers_mips_o32::getFloatRegister(int regNum) const { -#if defined(__mips_hard_float) && __mips_fpr == 64 - assert(validFloatRegister(regNum)); - return _floats[regNum - UNW_MIPS_F0]; -#else - _LIBUNWIND_ABORT("mips_o32 float support not implemented"); -#endif -} - -inline void Registers_mips_o32::setFloatRegister(int regNum, - double value) { -#if defined(__mips_hard_float) && __mips_fpr == 64 - assert(validFloatRegister(regNum)); - _floats[regNum - UNW_MIPS_F0] = value; -#else - _LIBUNWIND_ABORT("mips_o32 float support not implemented"); -#endif -} - -inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const { - return false; -} - -inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const { - _LIBUNWIND_ABORT("mips_o32 vector support not implemented"); -} - -inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) { - _LIBUNWIND_ABORT("mips_o32 vector support not implemented"); -} - -inline const char *Registers_mips_o32::getRegisterName(int regNum) { - switch (regNum) { - case UNW_MIPS_R0: - return "$0"; - case UNW_MIPS_R1: - return "$1"; - case UNW_MIPS_R2: - return "$2"; - case UNW_MIPS_R3: - return "$3"; - case UNW_MIPS_R4: - return "$4"; - case UNW_MIPS_R5: - return "$5"; - case UNW_MIPS_R6: - return "$6"; - case UNW_MIPS_R7: - return "$7"; - case UNW_MIPS_R8: - return "$8"; - case UNW_MIPS_R9: - return "$9"; - case UNW_MIPS_R10: - return "$10"; - case UNW_MIPS_R11: - return "$11"; - case UNW_MIPS_R12: - return "$12"; - case UNW_MIPS_R13: - return "$13"; - case UNW_MIPS_R14: - return "$14"; - case UNW_MIPS_R15: - return "$15"; - case UNW_MIPS_R16: - return "$16"; - case UNW_MIPS_R17: - return "$17"; - case UNW_MIPS_R18: - return "$18"; - case UNW_MIPS_R19: - return "$19"; - case UNW_MIPS_R20: - return "$20"; - case UNW_MIPS_R21: - return "$21"; - case UNW_MIPS_R22: - return "$22"; - case UNW_MIPS_R23: - return "$23"; - case UNW_MIPS_R24: - return "$24"; - case UNW_MIPS_R25: - return "$25"; - case UNW_MIPS_R26: - return "$26"; - case UNW_MIPS_R27: - return "$27"; - case UNW_MIPS_R28: - return "$28"; - case UNW_MIPS_R29: - return "$29"; - case UNW_MIPS_R30: - return "$30"; - case UNW_MIPS_R31: - return "$31"; - case UNW_MIPS_F0: - return "$f0"; - case UNW_MIPS_F1: - return "$f1"; - case UNW_MIPS_F2: - return "$f2"; - case UNW_MIPS_F3: - return "$f3"; - case UNW_MIPS_F4: - return "$f4"; - case UNW_MIPS_F5: - return "$f5"; - case UNW_MIPS_F6: - return "$f6"; - case UNW_MIPS_F7: - return "$f7"; - case UNW_MIPS_F8: - return "$f8"; - case UNW_MIPS_F9: - return "$f9"; - case UNW_MIPS_F10: - return "$f10"; - case UNW_MIPS_F11: - return "$f11"; - case UNW_MIPS_F12: - return "$f12"; - case UNW_MIPS_F13: - return "$f13"; - case UNW_MIPS_F14: - return "$f14"; - case UNW_MIPS_F15: - return "$f15"; - case UNW_MIPS_F16: - return "$f16"; - case UNW_MIPS_F17: - return "$f17"; - case UNW_MIPS_F18: - return "$f18"; - case UNW_MIPS_F19: - return "$f19"; - case UNW_MIPS_F20: - return "$f20"; - case UNW_MIPS_F21: - return "$f21"; - case UNW_MIPS_F22: - return "$f22"; - case UNW_MIPS_F23: - return "$f23"; - case UNW_MIPS_F24: - return "$f24"; - case UNW_MIPS_F25: - return "$f25"; - case UNW_MIPS_F26: - return "$f26"; - case UNW_MIPS_F27: - return "$f27"; - case UNW_MIPS_F28: - return "$f28"; - case UNW_MIPS_F29: - return "$f29"; - case UNW_MIPS_F30: - return "$f30"; - case UNW_MIPS_F31: - return "$f31"; - case UNW_MIPS_HI: - return "$hi"; - case UNW_MIPS_LO: - return "$lo"; - default: - return "unknown register"; - } -} -#endif // _LIBUNWIND_TARGET_MIPS_O32 - -#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) -/// Registers_mips_newabi holds the register state of a thread in a -/// MIPS process using NEWABI (the N32 or N64 ABIs). -class _LIBUNWIND_HIDDEN Registers_mips_newabi { -public: - Registers_mips_newabi(); - Registers_mips_newabi(const void *registers); - - bool validRegister(int num) const; - uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); - bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); - bool validVectorRegister(int num) const; - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - static const char *getRegisterName(int num); - void jumpto(); - static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } - static int getArch() { return REGISTERS_MIPS_NEWABI; } - - uint64_t getSP() const { return _registers.__r[29]; } - void setSP(uint64_t value) { _registers.__r[29] = value; } - uint64_t getIP() const { return _registers.__pc; } - void setIP(uint64_t value) { _registers.__pc = value; } - -private: - struct mips_newabi_thread_state_t { - uint64_t __r[32]; - uint64_t __pc; - uint64_t __hi; - uint64_t __lo; - }; - - mips_newabi_thread_state_t _registers; -#ifdef __mips_hard_float - double _floats[32]; -#endif -}; - -inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) { - static_assert((check_fit::does_fit), - "mips_newabi registers do not fit into unw_context_t"); - memcpy(&_registers, static_cast(registers), - sizeof(_registers)); -} - -inline Registers_mips_newabi::Registers_mips_newabi() { - memset(&_registers, 0, sizeof(_registers)); -} - -inline bool Registers_mips_newabi::validRegister(int regNum) const { - if (regNum == UNW_REG_IP) - return true; - if (regNum == UNW_REG_SP) - return true; - if (regNum < 0) - return false; - if (regNum <= UNW_MIPS_R31) - return true; -#if __mips_isa_rev != 6 - if (regNum == UNW_MIPS_HI) - return true; - if (regNum == UNW_MIPS_LO) - return true; -#endif - // FIXME: Hard float, DSP accumulator registers, MSA registers - return false; -} - -inline uint64_t Registers_mips_newabi::getRegister(int regNum) const { - if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) - return _registers.__r[regNum - UNW_MIPS_R0]; - - switch (regNum) { - case UNW_REG_IP: - return _registers.__pc; - case UNW_REG_SP: - return _registers.__r[29]; - case UNW_MIPS_HI: - return _registers.__hi; - case UNW_MIPS_LO: - return _registers.__lo; - } - _LIBUNWIND_ABORT("unsupported mips_newabi register"); -} - -inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) { - if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) { - _registers.__r[regNum - UNW_MIPS_R0] = value; - return; - } - - switch (regNum) { - case UNW_REG_IP: - _registers.__pc = value; - return; - case UNW_REG_SP: - _registers.__r[29] = value; - return; - case UNW_MIPS_HI: - _registers.__hi = value; - return; - case UNW_MIPS_LO: - _registers.__lo = value; - return; - } - _LIBUNWIND_ABORT("unsupported mips_newabi register"); -} - -inline bool Registers_mips_newabi::validFloatRegister(int regNum) const { -#ifdef __mips_hard_float - if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) - return true; -#endif - return false; -} - -inline double Registers_mips_newabi::getFloatRegister(int regNum) const { -#ifdef __mips_hard_float - assert(validFloatRegister(regNum)); - return _floats[regNum - UNW_MIPS_F0]; -#else - _LIBUNWIND_ABORT("mips_newabi float support not implemented"); -#endif -} - -inline void Registers_mips_newabi::setFloatRegister(int regNum, - double value) { -#ifdef __mips_hard_float - assert(validFloatRegister(regNum)); - _floats[regNum - UNW_MIPS_F0] = value; -#else - _LIBUNWIND_ABORT("mips_newabi float support not implemented"); -#endif -} - -inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const { - return false; -} - -inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const { - _LIBUNWIND_ABORT("mips_newabi vector support not implemented"); -} - -inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) { - _LIBUNWIND_ABORT("mips_newabi vector support not implemented"); -} - -inline const char *Registers_mips_newabi::getRegisterName(int regNum) { - switch (regNum) { - case UNW_MIPS_R0: - return "$0"; - case UNW_MIPS_R1: - return "$1"; - case UNW_MIPS_R2: - return "$2"; - case UNW_MIPS_R3: - return "$3"; - case UNW_MIPS_R4: - return "$4"; - case UNW_MIPS_R5: - return "$5"; - case UNW_MIPS_R6: - return "$6"; - case UNW_MIPS_R7: - return "$7"; - case UNW_MIPS_R8: - return "$8"; - case UNW_MIPS_R9: - return "$9"; - case UNW_MIPS_R10: - return "$10"; - case UNW_MIPS_R11: - return "$11"; - case UNW_MIPS_R12: - return "$12"; - case UNW_MIPS_R13: - return "$13"; - case UNW_MIPS_R14: - return "$14"; - case UNW_MIPS_R15: - return "$15"; - case UNW_MIPS_R16: - return "$16"; - case UNW_MIPS_R17: - return "$17"; - case UNW_MIPS_R18: - return "$18"; - case UNW_MIPS_R19: - return "$19"; - case UNW_MIPS_R20: - return "$20"; - case UNW_MIPS_R21: - return "$21"; - case UNW_MIPS_R22: - return "$22"; - case UNW_MIPS_R23: - return "$23"; - case UNW_MIPS_R24: - return "$24"; - case UNW_MIPS_R25: - return "$25"; - case UNW_MIPS_R26: - return "$26"; - case UNW_MIPS_R27: - return "$27"; - case UNW_MIPS_R28: - return "$28"; - case UNW_MIPS_R29: - return "$29"; - case UNW_MIPS_R30: - return "$30"; - case UNW_MIPS_R31: - return "$31"; - case UNW_MIPS_F0: - return "$f0"; - case UNW_MIPS_F1: - return "$f1"; - case UNW_MIPS_F2: - return "$f2"; - case UNW_MIPS_F3: - return "$f3"; - case UNW_MIPS_F4: - return "$f4"; - case UNW_MIPS_F5: - return "$f5"; - case UNW_MIPS_F6: - return "$f6"; - case UNW_MIPS_F7: - return "$f7"; - case UNW_MIPS_F8: - return "$f8"; - case UNW_MIPS_F9: - return "$f9"; - case UNW_MIPS_F10: - return "$f10"; - case UNW_MIPS_F11: - return "$f11"; - case UNW_MIPS_F12: - return "$f12"; - case UNW_MIPS_F13: - return "$f13"; - case UNW_MIPS_F14: - return "$f14"; - case UNW_MIPS_F15: - return "$f15"; - case UNW_MIPS_F16: - return "$f16"; - case UNW_MIPS_F17: - return "$f17"; - case UNW_MIPS_F18: - return "$f18"; - case UNW_MIPS_F19: - return "$f19"; - case UNW_MIPS_F20: - return "$f20"; - case UNW_MIPS_F21: - return "$f21"; - case UNW_MIPS_F22: - return "$f22"; - case UNW_MIPS_F23: - return "$f23"; - case UNW_MIPS_F24: - return "$f24"; - case UNW_MIPS_F25: - return "$f25"; - case UNW_MIPS_F26: - return "$f26"; - case UNW_MIPS_F27: - return "$f27"; - case UNW_MIPS_F28: - return "$f28"; - case UNW_MIPS_F29: - return "$f29"; - case UNW_MIPS_F30: - return "$f30"; - case UNW_MIPS_F31: - return "$f31"; - case UNW_MIPS_HI: - return "$hi"; - case UNW_MIPS_LO: - return "$lo"; - default: - return "unknown register"; - } -} -#endif // _LIBUNWIND_TARGET_MIPS_NEWABI - -#if defined(_LIBUNWIND_TARGET_SPARC) -/// Registers_sparc holds the register state of a thread in a 32-bit Sparc -/// process. -class _LIBUNWIND_HIDDEN Registers_sparc { -public: - Registers_sparc(); - Registers_sparc(const void *registers); - - bool validRegister(int num) const; - uint32_t getRegister(int num) const; - void setRegister(int num, uint32_t value); - bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); - bool validVectorRegister(int num) const; - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - static const char *getRegisterName(int num); - void jumpto(); - static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC; } - static int getArch() { return REGISTERS_SPARC; } - - uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; } - void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; } - uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; } - void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; } - -private: - struct sparc_thread_state_t { - unsigned int __regs[32]; - }; - - sparc_thread_state_t _registers; -}; - -inline Registers_sparc::Registers_sparc(const void *registers) { - static_assert((check_fit::does_fit), - "sparc registers do not fit into unw_context_t"); - memcpy(&_registers, static_cast(registers), - sizeof(_registers)); -} - -inline Registers_sparc::Registers_sparc() { - memset(&_registers, 0, sizeof(_registers)); -} - -inline bool Registers_sparc::validRegister(int regNum) const { - if (regNum == UNW_REG_IP) - return true; - if (regNum == UNW_REG_SP) - return true; - if (regNum < 0) - return false; - if (regNum <= UNW_SPARC_I7) - return true; - return false; -} - -inline uint32_t Registers_sparc::getRegister(int regNum) const { - if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) { - return _registers.__regs[regNum]; - } - - switch (regNum) { - case UNW_REG_IP: - return _registers.__regs[UNW_SPARC_O7]; - case UNW_REG_SP: - return _registers.__regs[UNW_SPARC_O6]; - } - _LIBUNWIND_ABORT("unsupported sparc register"); -} - -inline void Registers_sparc::setRegister(int regNum, uint32_t value) { - if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) { - _registers.__regs[regNum] = value; - return; - } - - switch (regNum) { - case UNW_REG_IP: - _registers.__regs[UNW_SPARC_O7] = value; - return; - case UNW_REG_SP: - _registers.__regs[UNW_SPARC_O6] = value; - return; - } - _LIBUNWIND_ABORT("unsupported sparc register"); -} - -inline bool Registers_sparc::validFloatRegister(int) const { return false; } - -inline double Registers_sparc::getFloatRegister(int) const { - _LIBUNWIND_ABORT("no Sparc float registers"); -} - -inline void Registers_sparc::setFloatRegister(int, double) { - _LIBUNWIND_ABORT("no Sparc float registers"); -} - -inline bool Registers_sparc::validVectorRegister(int) const { return false; } - -inline v128 Registers_sparc::getVectorRegister(int) const { - _LIBUNWIND_ABORT("no Sparc vector registers"); -} - -inline void Registers_sparc::setVectorRegister(int, v128) { - _LIBUNWIND_ABORT("no Sparc vector registers"); -} - -inline const char *Registers_sparc::getRegisterName(int regNum) { - switch (regNum) { - case UNW_REG_IP: - return "pc"; - case UNW_SPARC_G0: - return "g0"; - case UNW_SPARC_G1: - return "g1"; - case UNW_SPARC_G2: - return "g2"; - case UNW_SPARC_G3: - return "g3"; - case UNW_SPARC_G4: - return "g4"; - case UNW_SPARC_G5: - return "g5"; - case UNW_SPARC_G6: - return "g6"; - case UNW_SPARC_G7: - return "g7"; - case UNW_SPARC_O0: - return "o0"; - case UNW_SPARC_O1: - return "o1"; - case UNW_SPARC_O2: - return "o2"; - case UNW_SPARC_O3: - return "o3"; - case UNW_SPARC_O4: - return "o4"; - case UNW_SPARC_O5: - return "o5"; - case UNW_REG_SP: - case UNW_SPARC_O6: - return "sp"; - case UNW_SPARC_O7: - return "o7"; - case UNW_SPARC_L0: - return "l0"; - case UNW_SPARC_L1: - return "l1"; - case UNW_SPARC_L2: - return "l2"; - case UNW_SPARC_L3: - return "l3"; - case UNW_SPARC_L4: - return "l4"; - case UNW_SPARC_L5: - return "l5"; - case UNW_SPARC_L6: - return "l6"; - case UNW_SPARC_L7: - return "l7"; - case UNW_SPARC_I0: - return "i0"; - case UNW_SPARC_I1: - return "i1"; - case UNW_SPARC_I2: - return "i2"; - case UNW_SPARC_I3: - return "i3"; - case UNW_SPARC_I4: - return "i4"; - case UNW_SPARC_I5: - return "i5"; - case UNW_SPARC_I6: - return "fp"; - case UNW_SPARC_I7: - return "i7"; - default: - return "unknown register"; - } -} -#endif // _LIBUNWIND_TARGET_SPARC - -} // namespace libunwind - -#endif // __REGISTERS_HPP__ Index: head/contrib/llvm/projects/libunwind/src/UnwindLevel1.c =================================================================== --- head/contrib/llvm/projects/libunwind/src/UnwindLevel1.c (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/UnwindLevel1.c (nonexistent) @@ -1,509 +0,0 @@ -//===------------------------- UnwindLevel1.c -----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Implements C++ ABI Exception Handling Level 1 as documented at: -// http://mentorembedded.github.io/cxx-abi/abi-eh.html -// using libunwind -// -//===----------------------------------------------------------------------===// - -// ARM EHABI does not specify _Unwind_{Get,Set}{GR,IP}(). Thus, we are -// defining inline functions to delegate the function calls to -// _Unwind_VRS_{Get,Set}(). However, some applications might declare the -// function protetype directly (instead of including ), thus we need -// to export these functions from libunwind.so as well. -#define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 1 - -#include -#include -#include -#include -#include -#include - -#include "libunwind.h" -#include "unwind.h" -#include "config.h" - -#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) - -#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND - -static _Unwind_Reason_Code -unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { - unw_init_local(cursor, uc); - - // Walk each frame looking for a place to stop. - bool handlerNotFound = true; - while (handlerNotFound) { - // Ask libunwind to get next frame (skip over first which is - // _Unwind_RaiseException). - int stepResult = unw_step(cursor); - if (stepResult == 0) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached " - "bottom => _URC_END_OF_STACK", - (void *)exception_object); - return _URC_END_OF_STACK; - } else if (stepResult < 0) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => " - "_URC_FATAL_PHASE1_ERROR", - (void *)exception_object); - return _URC_FATAL_PHASE1_ERROR; - } - - // See if frame has code to run (has personality routine). - unw_proc_info_t frameInfo; - unw_word_t sp; - if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info " - "failed => _URC_FATAL_PHASE1_ERROR", - (void *)exception_object); - return _URC_FATAL_PHASE1_ERROR; - } - - // When tracing, print state information. - if (_LIBUNWIND_TRACING_UNWINDING) { - char functionBuf[512]; - const char *functionName = functionBuf; - unw_word_t offset; - if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), - &offset) != UNW_ESUCCESS) || - (frameInfo.start_ip + offset > frameInfo.end_ip)) - functionName = ".anonymous."; - unw_word_t pc; - unw_get_reg(cursor, UNW_REG_IP, &pc); - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR - ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "", - (void *)exception_object, pc, frameInfo.start_ip, functionName, - frameInfo.lsda, frameInfo.handler); - } - - // If there is a personality routine, ask it if it will want to stop at - // this frame. - if (frameInfo.handler != 0) { - __personality_routine p = - (__personality_routine)(uintptr_t)(frameInfo.handler); - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): calling personality function %p", - (void *)exception_object, (void *)(uintptr_t)p); - _Unwind_Reason_Code personalityResult = - (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class, - exception_object, (struct _Unwind_Context *)(cursor)); - switch (personalityResult) { - case _URC_HANDLER_FOUND: - // found a catch clause or locals that need destructing in this frame - // stop search and remember stack pointer at the frame - handlerNotFound = false; - unw_get_reg(cursor, UNW_REG_SP, &sp); - exception_object->private_2 = (uintptr_t)sp; - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND", - (void *)exception_object); - return _URC_NO_REASON; - - case _URC_CONTINUE_UNWIND: - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND", - (void *)exception_object); - // continue unwinding - break; - - default: - // something went wrong - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR", - (void *)exception_object); - return _URC_FATAL_PHASE1_ERROR; - } - } - } - return _URC_NO_REASON; -} - - -static _Unwind_Reason_Code -unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { - unw_init_local(cursor, uc); - - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", - (void *)exception_object); - - // Walk each frame until we reach where search phase said to stop. - while (true) { - - // Ask libunwind to get next frame (skip over first which is - // _Unwind_RaiseException). - int stepResult = unw_step(cursor); - if (stepResult == 0) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached " - "bottom => _URC_END_OF_STACK", - (void *)exception_object); - return _URC_END_OF_STACK; - } else if (stepResult < 0) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => " - "_URC_FATAL_PHASE1_ERROR", - (void *)exception_object); - return _URC_FATAL_PHASE2_ERROR; - } - - // Get info about this frame. - unw_word_t sp; - unw_proc_info_t frameInfo; - unw_get_reg(cursor, UNW_REG_SP, &sp); - if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info " - "failed => _URC_FATAL_PHASE1_ERROR", - (void *)exception_object); - return _URC_FATAL_PHASE2_ERROR; - } - - // When tracing, print state information. - if (_LIBUNWIND_TRACING_UNWINDING) { - char functionBuf[512]; - const char *functionName = functionBuf; - unw_word_t offset; - if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), - &offset) != UNW_ESUCCESS) || - (frameInfo.start_ip + offset > frameInfo.end_ip)) - functionName = ".anonymous."; - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR - ", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR - ", personality=0x%" PRIxPTR, - (void *)exception_object, frameInfo.start_ip, - functionName, sp, frameInfo.lsda, - frameInfo.handler); - } - - // If there is a personality routine, tell it we are unwinding. - if (frameInfo.handler != 0) { - __personality_routine p = - (__personality_routine)(uintptr_t)(frameInfo.handler); - _Unwind_Action action = _UA_CLEANUP_PHASE; - if (sp == exception_object->private_2) { - // Tell personality this was the frame it marked in phase 1. - action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME); - } - _Unwind_Reason_Code personalityResult = - (*p)(1, action, exception_object->exception_class, exception_object, - (struct _Unwind_Context *)(cursor)); - switch (personalityResult) { - case _URC_CONTINUE_UNWIND: - // Continue unwinding - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND", - (void *)exception_object); - if (sp == exception_object->private_2) { - // Phase 1 said we would stop at this frame, but we did not... - _LIBUNWIND_ABORT("during phase1 personality function said it would " - "stop here, but now in phase2 it did not stop here"); - } - break; - case _URC_INSTALL_CONTEXT: - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT", - (void *)exception_object); - // Personality routine says to transfer control to landing pad. - // We may get control back if landing pad calls _Unwind_Resume(). - if (_LIBUNWIND_TRACING_UNWINDING) { - unw_word_t pc; - unw_get_reg(cursor, UNW_REG_IP, &pc); - unw_get_reg(cursor, UNW_REG_SP, &sp); - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " - "user code with ip=0x%" PRIxPTR - ", sp=0x%" PRIxPTR, - (void *)exception_object, pc, sp); - } - unw_resume(cursor); - // unw_resume() only returns if there was an error. - return _URC_FATAL_PHASE2_ERROR; - default: - // Personality routine returned an unknown result code. - _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", - personalityResult); - return _URC_FATAL_PHASE2_ERROR; - } - } - } - - // Clean up phase did not resume at the frame that the search phase - // said it would... - return _URC_FATAL_PHASE2_ERROR; -} - -static _Unwind_Reason_Code -unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, - _Unwind_Exception *exception_object, - _Unwind_Stop_Fn stop, void *stop_parameter) { - unw_init_local(cursor, uc); - - // Walk each frame until we reach where search phase said to stop - while (unw_step(cursor) > 0) { - - // Update info about this frame. - unw_proc_info_t frameInfo; - if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step " - "failed => _URC_END_OF_STACK", - (void *)exception_object); - return _URC_FATAL_PHASE2_ERROR; - } - - // When tracing, print state information. - if (_LIBUNWIND_TRACING_UNWINDING) { - char functionBuf[512]; - const char *functionName = functionBuf; - unw_word_t offset; - if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), - &offset) != UNW_ESUCCESS) || - (frameInfo.start_ip + offset > frameInfo.end_ip)) - functionName = ".anonymous."; - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR - ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR, - (void *)exception_object, frameInfo.start_ip, functionName, - frameInfo.lsda, frameInfo.handler); - } - - // Call stop function at each frame. - _Unwind_Action action = - (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); - _Unwind_Reason_Code stopResult = - (*stop)(1, action, exception_object->exception_class, exception_object, - (struct _Unwind_Context *)(cursor), stop_parameter); - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): stop function returned %d", - (void *)exception_object, stopResult); - if (stopResult != _URC_NO_REASON) { - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): stopped by stop function", - (void *)exception_object); - return _URC_FATAL_PHASE2_ERROR; - } - - // If there is a personality routine, tell it we are unwinding. - if (frameInfo.handler != 0) { - __personality_routine p = - (__personality_routine)(intptr_t)(frameInfo.handler); - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", - (void *)exception_object, (void *)(uintptr_t)p); - _Unwind_Reason_Code personalityResult = - (*p)(1, action, exception_object->exception_class, exception_object, - (struct _Unwind_Context *)(cursor)); - switch (personalityResult) { - case _URC_CONTINUE_UNWIND: - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "personality returned " - "_URC_CONTINUE_UNWIND", - (void *)exception_object); - // Destructors called, continue unwinding - break; - case _URC_INSTALL_CONTEXT: - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "personality returned " - "_URC_INSTALL_CONTEXT", - (void *)exception_object); - // We may get control back if landing pad calls _Unwind_Resume(). - unw_resume(cursor); - break; - default: - // Personality routine returned an unknown result code. - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "personality returned %d, " - "_URC_FATAL_PHASE2_ERROR", - (void *)exception_object, personalityResult); - return _URC_FATAL_PHASE2_ERROR; - } - } - } - - // Call stop function one last time and tell it we've reached the end - // of the stack. - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " - "function with _UA_END_OF_STACK", - (void *)exception_object); - _Unwind_Action lastAction = - (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); - (*stop)(1, lastAction, exception_object->exception_class, exception_object, - (struct _Unwind_Context *)(cursor), stop_parameter); - - // Clean up phase did not resume at the frame that the search phase said it - // would. - return _URC_FATAL_PHASE2_ERROR; -} - - -/// Called by __cxa_throw. Only returns if there is a fatal error. -_LIBUNWIND_EXPORT _Unwind_Reason_Code -_Unwind_RaiseException(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)", - (void *)exception_object); - unw_context_t uc; - unw_cursor_t cursor; - unw_getcontext(&uc); - - // Mark that this is a non-forced unwind, so _Unwind_Resume() - // can do the right thing. - exception_object->private_1 = 0; - exception_object->private_2 = 0; - - // phase 1: the search phase - _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object); - if (phase1 != _URC_NO_REASON) - return phase1; - - // phase 2: the clean up phase - return unwind_phase2(&uc, &cursor, exception_object); -} - - - -/// When _Unwind_RaiseException() is in phase2, it hands control -/// to the personality function at each frame. The personality -/// may force a jump to a landing pad in that function, the landing -/// pad code may then call _Unwind_Resume() to continue with the -/// unwinding. Note: the call to _Unwind_Resume() is from compiler -/// geneated user code. All other _Unwind_* routines are called -/// by the C++ runtime __cxa_* routines. -/// -/// Note: re-throwing an exception (as opposed to continuing the unwind) -/// is implemented by having the code call __cxa_rethrow() which -/// in turn calls _Unwind_Resume_or_Rethrow(). -_LIBUNWIND_EXPORT void -_Unwind_Resume(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object); - unw_context_t uc; - unw_cursor_t cursor; - unw_getcontext(&uc); - - if (exception_object->private_1 != 0) - unwind_phase2_forced(&uc, &cursor, exception_object, - (_Unwind_Stop_Fn) exception_object->private_1, - (void *)exception_object->private_2); - else - unwind_phase2(&uc, &cursor, exception_object); - - // Clients assume _Unwind_Resume() does not return, so all we can do is abort. - _LIBUNWIND_ABORT("_Unwind_Resume() can't return"); -} - - - -/// Not used by C++. -/// Unwinds stack, calling "stop" function at each frame. -/// Could be used to implement longjmp(). -_LIBUNWIND_EXPORT _Unwind_Reason_Code -_Unwind_ForcedUnwind(_Unwind_Exception *exception_object, - _Unwind_Stop_Fn stop, void *stop_parameter) { - _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)", - (void *)exception_object, (void *)(uintptr_t)stop); - unw_context_t uc; - unw_cursor_t cursor; - unw_getcontext(&uc); - - // Mark that this is a forced unwind, so _Unwind_Resume() can do - // the right thing. - exception_object->private_1 = (uintptr_t) stop; - exception_object->private_2 = (uintptr_t) stop_parameter; - - // do it - return unwind_phase2_forced(&uc, &cursor, exception_object, stop, stop_parameter); -} - - -/// Called by personality handler during phase 2 to get LSDA for current frame. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { - unw_cursor_t *cursor = (unw_cursor_t *)context; - unw_proc_info_t frameInfo; - uintptr_t result = 0; - if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) - result = (uintptr_t)frameInfo.lsda; - _LIBUNWIND_TRACE_API( - "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR, - (void *)context, result); - if (result != 0) { - if (*((uint8_t *)result) != 0xFF) - _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF", - result); - } - return result; -} - - -/// Called by personality handler during phase 2 to find the start of the -/// function. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetRegionStart(struct _Unwind_Context *context) { - unw_cursor_t *cursor = (unw_cursor_t *)context; - unw_proc_info_t frameInfo; - uintptr_t result = 0; - if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) - result = (uintptr_t)frameInfo.start_ip; - _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR, - (void *)context, result); - return result; -} - -#endif // !_LIBUNWIND_SUPPORT_SEH_UNWIND - -/// Called by personality handler during phase 2 if a foreign exception -// is caught. -_LIBUNWIND_EXPORT void -_Unwind_DeleteException(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)", - (void *)exception_object); - if (exception_object->exception_cleanup != NULL) - (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, - exception_object); -} - -/// Called by personality handler during phase 2 to get register values. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetGR(struct _Unwind_Context *context, int index) { - unw_cursor_t *cursor = (unw_cursor_t *)context; - unw_word_t result; - unw_get_reg(cursor, index, &result); - _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIxPTR, - (void *)context, index, result); - return (uintptr_t)result; -} - -/// Called by personality handler during phase 2 to alter register values. -_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, - uintptr_t value) { - _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIxPTR - ")", - (void *)context, index, value); - unw_cursor_t *cursor = (unw_cursor_t *)context; - unw_set_reg(cursor, index, value); -} - -/// Called by personality handler during phase 2 to get instruction pointer. -_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { - unw_cursor_t *cursor = (unw_cursor_t *)context; - unw_word_t result; - unw_get_reg(cursor, UNW_REG_IP, &result); - _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR, - (void *)context, result); - return (uintptr_t)result; -} - -/// Called by personality handler during phase 2 to alter instruction pointer, -/// such as setting where the landing pad is, so _Unwind_Resume() will -/// start executing in the landing pad. -_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, - uintptr_t value) { - _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIxPTR ")", - (void *)context, value); - unw_cursor_t *cursor = (unw_cursor_t *)context; - unw_set_reg(cursor, UNW_REG_IP, value); -} - -#endif // !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) Property changes on: head/contrib/llvm/projects/libunwind/src/UnwindLevel1.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/Unwind-EHABI.cpp =================================================================== --- head/contrib/llvm/projects/libunwind/src/Unwind-EHABI.cpp (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/Unwind-EHABI.cpp (nonexistent) @@ -1,991 +0,0 @@ -//===--------------------------- Unwind-EHABI.cpp -------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Implements ARM zero-cost C++ exceptions -// -//===----------------------------------------------------------------------===// - -#include "Unwind-EHABI.h" - -#if defined(_LIBUNWIND_ARM_EHABI) - -#include -#include -#include -#include -#include -#include - -#include - -#include "config.h" -#include "libunwind.h" -#include "libunwind_ext.h" -#include "unwind.h" - -namespace { - -// Strange order: take words in order, but inside word, take from most to least -// signinficant byte. -uint8_t getByte(const uint32_t* data, size_t offset) { - const uint8_t* byteData = reinterpret_cast(data); - return byteData[(offset & ~(size_t)0x03) + (3 - (offset & (size_t)0x03))]; -} - -const char* getNextWord(const char* data, uint32_t* out) { - *out = *reinterpret_cast(data); - return data + 4; -} - -const char* getNextNibble(const char* data, uint32_t* out) { - *out = *reinterpret_cast(data); - return data + 2; -} - -struct Descriptor { - // See # 9.2 - typedef enum { - SU16 = 0, // Short descriptor, 16-bit entries - LU16 = 1, // Long descriptor, 16-bit entries - LU32 = 3, // Long descriptor, 32-bit entries - RESERVED0 = 4, RESERVED1 = 5, RESERVED2 = 6, RESERVED3 = 7, - RESERVED4 = 8, RESERVED5 = 9, RESERVED6 = 10, RESERVED7 = 11, - RESERVED8 = 12, RESERVED9 = 13, RESERVED10 = 14, RESERVED11 = 15 - } Format; - - // See # 9.2 - typedef enum { - CLEANUP = 0x0, - FUNC = 0x1, - CATCH = 0x2, - INVALID = 0x4 - } Kind; -}; - -_Unwind_Reason_Code ProcessDescriptors( - _Unwind_State state, - _Unwind_Control_Block* ucbp, - struct _Unwind_Context* context, - Descriptor::Format format, - const char* descriptorStart, - uint32_t flags) { - - // EHT is inlined in the index using compact form. No descriptors. #5 - if (flags & 0x1) - return _URC_CONTINUE_UNWIND; - - // TODO: We should check the state here, and determine whether we need to - // perform phase1 or phase2 unwinding. - (void)state; - - const char* descriptor = descriptorStart; - uint32_t descriptorWord; - getNextWord(descriptor, &descriptorWord); - while (descriptorWord) { - // Read descriptor based on # 9.2. - uint32_t length; - uint32_t offset; - switch (format) { - case Descriptor::LU32: - descriptor = getNextWord(descriptor, &length); - descriptor = getNextWord(descriptor, &offset); - case Descriptor::LU16: - descriptor = getNextNibble(descriptor, &length); - descriptor = getNextNibble(descriptor, &offset); - default: - assert(false); - return _URC_FAILURE; - } - - // See # 9.2 table for decoding the kind of descriptor. It's a 2-bit value. - Descriptor::Kind kind = - static_cast((length & 0x1) | ((offset & 0x1) << 1)); - - // Clear off flag from last bit. - length &= ~1u; - offset &= ~1u; - uintptr_t scopeStart = ucbp->pr_cache.fnstart + offset; - uintptr_t scopeEnd = scopeStart + length; - uintptr_t pc = _Unwind_GetIP(context); - bool isInScope = (scopeStart <= pc) && (pc < scopeEnd); - - switch (kind) { - case Descriptor::CLEANUP: { - // TODO(ajwong): Handle cleanup descriptors. - break; - } - case Descriptor::FUNC: { - // TODO(ajwong): Handle function descriptors. - break; - } - case Descriptor::CATCH: { - // Catch descriptors require gobbling one more word. - uint32_t landing_pad; - descriptor = getNextWord(descriptor, &landing_pad); - - if (isInScope) { - // TODO(ajwong): This is only phase1 compatible logic. Implement - // phase2. - landing_pad = signExtendPrel31(landing_pad & ~0x80000000); - if (landing_pad == 0xffffffff) { - return _URC_HANDLER_FOUND; - } else if (landing_pad == 0xfffffffe) { - return _URC_FAILURE; - } else { - /* - bool is_reference_type = landing_pad & 0x80000000; - void* matched_object; - if (__cxxabiv1::__cxa_type_match( - ucbp, reinterpret_cast(landing_pad), - is_reference_type, - &matched_object) != __cxxabiv1::ctm_failed) - return _URC_HANDLER_FOUND; - */ - _LIBUNWIND_ABORT("Type matching not implemented"); - } - } - break; - } - default: - _LIBUNWIND_ABORT("Invalid descriptor kind found."); - } - - getNextWord(descriptor, &descriptorWord); - } - - return _URC_CONTINUE_UNWIND; -} - -static _Unwind_Reason_Code unwindOneFrame(_Unwind_State state, - _Unwind_Control_Block* ucbp, - struct _Unwind_Context* context) { - // Read the compact model EHT entry's header # 6.3 - const uint32_t* unwindingData = ucbp->pr_cache.ehtp; - assert((*unwindingData & 0xf0000000) == 0x80000000 && "Must be a compact entry"); - Descriptor::Format format = - static_cast((*unwindingData & 0x0f000000) >> 24); - - const char *lsda = - reinterpret_cast(_Unwind_GetLanguageSpecificData(context)); - - // Handle descriptors before unwinding so they are processed in the context - // of the correct stack frame. - _Unwind_Reason_Code result = - ProcessDescriptors(state, ucbp, context, format, lsda, - ucbp->pr_cache.additional); - - if (result != _URC_CONTINUE_UNWIND) - return result; - - if (unw_step(reinterpret_cast(context)) != UNW_STEP_SUCCESS) - return _URC_FAILURE; - return _URC_CONTINUE_UNWIND; -} - -// Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_CORE / -// _UVRSD_UINT32. -uint32_t RegisterMask(uint8_t start, uint8_t count_minus_one) { - return ((1U << (count_minus_one + 1)) - 1) << start; -} - -// Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_VFP / -// _UVRSD_DOUBLE. -uint32_t RegisterRange(uint8_t start, uint8_t count_minus_one) { - return ((uint32_t)start << 16) | ((uint32_t)count_minus_one + 1); -} - -} // end anonymous namespace - -/** - * Decodes an EHT entry. - * - * @param data Pointer to EHT. - * @param[out] off Offset from return value (in bytes) to begin interpretation. - * @param[out] len Number of bytes in unwind code. - * @return Pointer to beginning of unwind code. - */ -extern "C" const uint32_t* -decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) { - if ((*data & 0x80000000) == 0) { - // 6.2: Generic Model - // - // EHT entry is a prel31 pointing to the PR, followed by data understood - // only by the personality routine. Fortunately, all existing assembler - // implementations, including GNU assembler, LLVM integrated assembler, - // and ARM assembler, assume that the unwind opcodes come after the - // personality rountine address. - *off = 1; // First byte is size data. - *len = (((data[1] >> 24) & 0xff) + 1) * 4; - data++; // Skip the first word, which is the prel31 offset. - } else { - // 6.3: ARM Compact Model - // - // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeded - // by format: - Descriptor::Format format = - static_cast((*data & 0x0f000000) >> 24); - switch (format) { - case Descriptor::SU16: - *len = 4; - *off = 1; - break; - case Descriptor::LU16: - case Descriptor::LU32: - *len = 4 + 4 * ((*data & 0x00ff0000) >> 16); - *off = 2; - break; - default: - return nullptr; - } - } - return data; -} - -_LIBUNWIND_EXPORT _Unwind_Reason_Code -_Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, - size_t offset, size_t len) { - bool wrotePC = false; - bool finish = false; - while (offset < len && !finish) { - uint8_t byte = getByte(data, offset++); - if ((byte & 0x80) == 0) { - uint32_t sp; - _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); - if (byte & 0x40) - sp -= (((uint32_t)byte & 0x3f) << 2) + 4; - else - sp += ((uint32_t)byte << 2) + 4; - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); - } else { - switch (byte & 0xf0) { - case 0x80: { - if (offset >= len) - return _URC_FAILURE; - uint32_t registers = - (((uint32_t)byte & 0x0f) << 12) | - (((uint32_t)getByte(data, offset++)) << 4); - if (!registers) - return _URC_FAILURE; - if (registers & (1 << 15)) - wrotePC = true; - _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32); - break; - } - case 0x90: { - uint8_t reg = byte & 0x0f; - if (reg == 13 || reg == 15) - return _URC_FAILURE; - uint32_t sp; - _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_R0 + reg, - _UVRSD_UINT32, &sp); - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp); - break; - } - case 0xa0: { - uint32_t registers = RegisterMask(4, byte & 0x07); - if (byte & 0x08) - registers |= 1 << 14; - _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32); - break; - } - case 0xb0: { - switch (byte) { - case 0xb0: - finish = true; - break; - case 0xb1: { - if (offset >= len) - return _URC_FAILURE; - uint8_t registers = getByte(data, offset++); - if (registers & 0xf0 || !registers) - return _URC_FAILURE; - _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32); - break; - } - case 0xb2: { - uint32_t addend = 0; - uint32_t shift = 0; - // This decodes a uleb128 value. - while (true) { - if (offset >= len) - return _URC_FAILURE; - uint32_t v = getByte(data, offset++); - addend |= (v & 0x7f) << shift; - if ((v & 0x80) == 0) - break; - shift += 7; - } - uint32_t sp; - _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp); - sp += 0x204 + (addend << 2); - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp); - break; - } - case 0xb3: { - uint8_t v = getByte(data, offset++); - _Unwind_VRS_Pop(context, _UVRSC_VFP, - RegisterRange(static_cast(v >> 4), - v & 0x0f), _UVRSD_VFPX); - break; - } - case 0xb4: - case 0xb5: - case 0xb6: - case 0xb7: - return _URC_FAILURE; - default: - _Unwind_VRS_Pop(context, _UVRSC_VFP, - RegisterRange(8, byte & 0x07), _UVRSD_VFPX); - break; - } - break; - } - case 0xc0: { - switch (byte) { -#if defined(__ARM_WMMX) - case 0xc0: - case 0xc1: - case 0xc2: - case 0xc3: - case 0xc4: - case 0xc5: - _Unwind_VRS_Pop(context, _UVRSC_WMMXD, - RegisterRange(10, byte & 0x7), _UVRSD_DOUBLE); - break; - case 0xc6: { - uint8_t v = getByte(data, offset++); - uint8_t start = static_cast(v >> 4); - uint8_t count_minus_one = v & 0xf; - if (start + count_minus_one >= 16) - return _URC_FAILURE; - _Unwind_VRS_Pop(context, _UVRSC_WMMXD, - RegisterRange(start, count_minus_one), - _UVRSD_DOUBLE); - break; - } - case 0xc7: { - uint8_t v = getByte(data, offset++); - if (!v || v & 0xf0) - return _URC_FAILURE; - _Unwind_VRS_Pop(context, _UVRSC_WMMXC, v, _UVRSD_DOUBLE); - break; - } -#endif - case 0xc8: - case 0xc9: { - uint8_t v = getByte(data, offset++); - uint8_t start = - static_cast(((byte == 0xc8) ? 16 : 0) + (v >> 4)); - uint8_t count_minus_one = v & 0xf; - if (start + count_minus_one >= 32) - return _URC_FAILURE; - _Unwind_VRS_Pop(context, _UVRSC_VFP, - RegisterRange(start, count_minus_one), - _UVRSD_DOUBLE); - break; - } - default: - return _URC_FAILURE; - } - break; - } - case 0xd0: { - if (byte & 0x08) - return _URC_FAILURE; - _Unwind_VRS_Pop(context, _UVRSC_VFP, RegisterRange(8, byte & 0x7), - _UVRSD_DOUBLE); - break; - } - default: - return _URC_FAILURE; - } - } - } - if (!wrotePC) { - uint32_t lr; - _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr); - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr); - } - return _URC_CONTINUE_UNWIND; -} - -extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code -__aeabi_unwind_cpp_pr0(_Unwind_State state, _Unwind_Control_Block *ucbp, - _Unwind_Context *context) { - return unwindOneFrame(state, ucbp, context); -} - -extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code -__aeabi_unwind_cpp_pr1(_Unwind_State state, _Unwind_Control_Block *ucbp, - _Unwind_Context *context) { - return unwindOneFrame(state, ucbp, context); -} - -extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code -__aeabi_unwind_cpp_pr2(_Unwind_State state, _Unwind_Control_Block *ucbp, - _Unwind_Context *context) { - return unwindOneFrame(state, ucbp, context); -} - -static _Unwind_Reason_Code -unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { - // EHABI #7.3 discusses preserving the VRS in a "temporary VRS" during - // phase 1 and then restoring it to the "primary VRS" for phase 2. The - // effect is phase 2 doesn't see any of the VRS manipulations from phase 1. - // In this implementation, the phases don't share the VRS backing store. - // Instead, they are passed the original |uc| and they create a new VRS - // from scratch thus achieving the same effect. - unw_init_local(cursor, uc); - - // Walk each frame looking for a place to stop. - for (bool handlerNotFound = true; handlerNotFound;) { - - // See if frame has code to run (has personality routine). - unw_proc_info_t frameInfo; - if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info " - "failed => _URC_FATAL_PHASE1_ERROR", - static_cast(exception_object)); - return _URC_FATAL_PHASE1_ERROR; - } - - // When tracing, print state information. - if (_LIBUNWIND_TRACING_UNWINDING) { - char functionBuf[512]; - const char *functionName = functionBuf; - unw_word_t offset; - if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), - &offset) != UNW_ESUCCESS) || - (frameInfo.start_ip + offset > frameInfo.end_ip)) - functionName = ".anonymous."; - unw_word_t pc; - unw_get_reg(cursor, UNW_REG_IP, &pc); - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR ", func=%s, " - "lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR, - static_cast(exception_object), pc, - frameInfo.start_ip, functionName, - frameInfo.lsda, frameInfo.handler); - } - - // If there is a personality routine, ask it if it will want to stop at - // this frame. - if (frameInfo.handler != 0) { - __personality_routine p = - (__personality_routine)(long)(frameInfo.handler); - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): calling personality function %p", - static_cast(exception_object), - reinterpret_cast(reinterpret_cast(p))); - struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor); - exception_object->pr_cache.fnstart = frameInfo.start_ip; - exception_object->pr_cache.ehtp = - (_Unwind_EHT_Header *)frameInfo.unwind_info; - exception_object->pr_cache.additional = frameInfo.flags; - _Unwind_Reason_Code personalityResult = - (*p)(_US_VIRTUAL_UNWIND_FRAME, exception_object, context); - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): personality result %d start_ip %x ehtp %p " - "additional %x", - static_cast(exception_object), personalityResult, - exception_object->pr_cache.fnstart, - static_cast(exception_object->pr_cache.ehtp), - exception_object->pr_cache.additional); - switch (personalityResult) { - case _URC_HANDLER_FOUND: - // found a catch clause or locals that need destructing in this frame - // stop search and remember stack pointer at the frame - handlerNotFound = false; - // p should have initialized barrier_cache. EHABI #7.3.5 - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND", - static_cast(exception_object)); - return _URC_NO_REASON; - - case _URC_CONTINUE_UNWIND: - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND", - static_cast(exception_object)); - // continue unwinding - break; - - // EHABI #7.3.3 - case _URC_FAILURE: - return _URC_FAILURE; - - default: - // something went wrong - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR", - static_cast(exception_object)); - return _URC_FATAL_PHASE1_ERROR; - } - } - } - return _URC_NO_REASON; -} - -static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, - _Unwind_Exception *exception_object, - bool resume) { - // See comment at the start of unwind_phase1 regarding VRS integrity. - unw_init_local(cursor, uc); - - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", - static_cast(exception_object)); - int frame_count = 0; - - // Walk each frame until we reach where search phase said to stop. - while (true) { - // Ask libunwind to get next frame (skip over first which is - // _Unwind_RaiseException or _Unwind_Resume). - // - // Resume only ever makes sense for 1 frame. - _Unwind_State state = - resume ? _US_UNWIND_FRAME_RESUME : _US_UNWIND_FRAME_STARTING; - if (resume && frame_count == 1) { - // On a resume, first unwind the _Unwind_Resume() frame. The next frame - // is now the landing pad for the cleanup from a previous execution of - // phase2. To continue unwindingly correctly, replace VRS[15] with the - // IP of the frame that the previous run of phase2 installed the context - // for. After this, continue unwinding as if normal. - // - // See #7.4.6 for details. - unw_set_reg(cursor, UNW_REG_IP, - exception_object->unwinder_cache.reserved2); - resume = false; - } - - // Get info about this frame. - unw_word_t sp; - unw_proc_info_t frameInfo; - unw_get_reg(cursor, UNW_REG_SP, &sp); - if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info " - "failed => _URC_FATAL_PHASE2_ERROR", - static_cast(exception_object)); - return _URC_FATAL_PHASE2_ERROR; - } - - // When tracing, print state information. - if (_LIBUNWIND_TRACING_UNWINDING) { - char functionBuf[512]; - const char *functionName = functionBuf; - unw_word_t offset; - if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), - &offset) != UNW_ESUCCESS) || - (frameInfo.start_ip + offset > frameInfo.end_ip)) - functionName = ".anonymous."; - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR ", func=%s, sp=0x%" PRIxPTR ", " - "lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "", - static_cast(exception_object), frameInfo.start_ip, - functionName, sp, frameInfo.lsda, - frameInfo.handler); - } - - // If there is a personality routine, tell it we are unwinding. - if (frameInfo.handler != 0) { - __personality_routine p = - (__personality_routine)(long)(frameInfo.handler); - struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor); - // EHABI #7.2 - exception_object->pr_cache.fnstart = frameInfo.start_ip; - exception_object->pr_cache.ehtp = - (_Unwind_EHT_Header *)frameInfo.unwind_info; - exception_object->pr_cache.additional = frameInfo.flags; - _Unwind_Reason_Code personalityResult = - (*p)(state, exception_object, context); - switch (personalityResult) { - case _URC_CONTINUE_UNWIND: - // Continue unwinding - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND", - static_cast(exception_object)); - // EHABI #7.2 - if (sp == exception_object->barrier_cache.sp) { - // Phase 1 said we would stop at this frame, but we did not... - _LIBUNWIND_ABORT("during phase1 personality function said it would " - "stop here, but now in phase2 it did not stop here"); - } - break; - case _URC_INSTALL_CONTEXT: - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT", - static_cast(exception_object)); - // Personality routine says to transfer control to landing pad. - // We may get control back if landing pad calls _Unwind_Resume(). - if (_LIBUNWIND_TRACING_UNWINDING) { - unw_word_t pc; - unw_get_reg(cursor, UNW_REG_IP, &pc); - unw_get_reg(cursor, UNW_REG_SP, &sp); - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " - "user code with ip=0x%" PRIxPTR ", sp=0x%" PRIxPTR, - static_cast(exception_object), - pc, sp); - } - - { - // EHABI #7.4.1 says we need to preserve pc for when _Unwind_Resume - // is called back, to find this same frame. - unw_word_t pc; - unw_get_reg(cursor, UNW_REG_IP, &pc); - exception_object->unwinder_cache.reserved2 = (uint32_t)pc; - } - unw_resume(cursor); - // unw_resume() only returns if there was an error. - return _URC_FATAL_PHASE2_ERROR; - - // # EHABI #7.4.3 - case _URC_FAILURE: - abort(); - - default: - // Personality routine returned an unknown result code. - _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", - personalityResult); - return _URC_FATAL_PHASE2_ERROR; - } - } - frame_count++; - } - - // Clean up phase did not resume at the frame that the search phase - // said it would... - return _URC_FATAL_PHASE2_ERROR; -} - -/// Called by __cxa_throw. Only returns if there is a fatal error. -_LIBUNWIND_EXPORT _Unwind_Reason_Code -_Unwind_RaiseException(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)", - static_cast(exception_object)); - unw_context_t uc; - unw_cursor_t cursor; - unw_getcontext(&uc); - - // This field for is for compatibility with GCC to say this isn't a forced - // unwind. EHABI #7.2 - exception_object->unwinder_cache.reserved1 = 0; - - // phase 1: the search phase - _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object); - if (phase1 != _URC_NO_REASON) - return phase1; - - // phase 2: the clean up phase - return unwind_phase2(&uc, &cursor, exception_object, false); -} - -_LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) { - // This is to be called when exception handling completes to give us a chance - // to perform any housekeeping. EHABI #7.2. But we have nothing to do here. - (void)exception_object; -} - -/// When _Unwind_RaiseException() is in phase2, it hands control -/// to the personality function at each frame. The personality -/// may force a jump to a landing pad in that function, the landing -/// pad code may then call _Unwind_Resume() to continue with the -/// unwinding. Note: the call to _Unwind_Resume() is from compiler -/// geneated user code. All other _Unwind_* routines are called -/// by the C++ runtime __cxa_* routines. -/// -/// Note: re-throwing an exception (as opposed to continuing the unwind) -/// is implemented by having the code call __cxa_rethrow() which -/// in turn calls _Unwind_Resume_or_Rethrow(). -_LIBUNWIND_EXPORT void -_Unwind_Resume(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", - static_cast(exception_object)); - unw_context_t uc; - unw_cursor_t cursor; - unw_getcontext(&uc); - - // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0, - // which is in the same position as private_1 below. - // TODO(ajwong): Who wronte the above? Why is it true? - unwind_phase2(&uc, &cursor, exception_object, true); - - // Clients assume _Unwind_Resume() does not return, so all we can do is abort. - _LIBUNWIND_ABORT("_Unwind_Resume() can't return"); -} - -/// Called by personality handler during phase 2 to get LSDA for current frame. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { - unw_cursor_t *cursor = (unw_cursor_t *)context; - unw_proc_info_t frameInfo; - uintptr_t result = 0; - if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) - result = (uintptr_t)frameInfo.lsda; - _LIBUNWIND_TRACE_API( - "_Unwind_GetLanguageSpecificData(context=%p) => 0x%llx", - static_cast(context), (long long)result); - return result; -} - -static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation, - void* valuep) { - uint64_t value = 0; - switch (representation) { - case _UVRSD_UINT32: - case _UVRSD_FLOAT: - memcpy(&value, valuep, sizeof(uint32_t)); - break; - - case _UVRSD_VFPX: - case _UVRSD_UINT64: - case _UVRSD_DOUBLE: - memcpy(&value, valuep, sizeof(uint64_t)); - break; - } - return value; -} - -_LIBUNWIND_EXPORT _Unwind_VRS_Result -_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, - uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep) { - _LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, " - "rep=%d, value=0x%llX)", - static_cast(context), regclass, regno, - representation, - ValueAsBitPattern(representation, valuep)); - unw_cursor_t *cursor = (unw_cursor_t *)context; - switch (regclass) { - case _UVRSC_CORE: - if (representation != _UVRSD_UINT32 || regno > 15) - return _UVRSR_FAILED; - return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno), - *(unw_word_t *)valuep) == UNW_ESUCCESS - ? _UVRSR_OK - : _UVRSR_FAILED; - case _UVRSC_VFP: - if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE) - return _UVRSR_FAILED; - if (representation == _UVRSD_VFPX) { - // Can only touch d0-15 with FSTMFDX. - if (regno > 15) - return _UVRSR_FAILED; - unw_save_vfp_as_X(cursor); - } else { - if (regno > 31) - return _UVRSR_FAILED; - } - return unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno), - *(unw_fpreg_t *)valuep) == UNW_ESUCCESS - ? _UVRSR_OK - : _UVRSR_FAILED; -#if defined(__ARM_WMMX) - case _UVRSC_WMMXC: - if (representation != _UVRSD_UINT32 || regno > 3) - return _UVRSR_FAILED; - return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno), - *(unw_word_t *)valuep) == UNW_ESUCCESS - ? _UVRSR_OK - : _UVRSR_FAILED; - case _UVRSC_WMMXD: - if (representation != _UVRSD_DOUBLE || regno > 31) - return _UVRSR_FAILED; - return unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno), - *(unw_fpreg_t *)valuep) == UNW_ESUCCESS - ? _UVRSR_OK - : _UVRSR_FAILED; -#else - case _UVRSC_WMMXC: - case _UVRSC_WMMXD: - break; -#endif - } - _LIBUNWIND_ABORT("unsupported register class"); -} - -static _Unwind_VRS_Result -_Unwind_VRS_Get_Internal(_Unwind_Context *context, - _Unwind_VRS_RegClass regclass, uint32_t regno, - _Unwind_VRS_DataRepresentation representation, - void *valuep) { - unw_cursor_t *cursor = (unw_cursor_t *)context; - switch (regclass) { - case _UVRSC_CORE: - if (representation != _UVRSD_UINT32 || regno > 15) - return _UVRSR_FAILED; - return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno), - (unw_word_t *)valuep) == UNW_ESUCCESS - ? _UVRSR_OK - : _UVRSR_FAILED; - case _UVRSC_VFP: - if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE) - return _UVRSR_FAILED; - if (representation == _UVRSD_VFPX) { - // Can only touch d0-15 with FSTMFDX. - if (regno > 15) - return _UVRSR_FAILED; - unw_save_vfp_as_X(cursor); - } else { - if (regno > 31) - return _UVRSR_FAILED; - } - return unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno), - (unw_fpreg_t *)valuep) == UNW_ESUCCESS - ? _UVRSR_OK - : _UVRSR_FAILED; -#if defined(__ARM_WMMX) - case _UVRSC_WMMXC: - if (representation != _UVRSD_UINT32 || regno > 3) - return _UVRSR_FAILED; - return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno), - (unw_word_t *)valuep) == UNW_ESUCCESS - ? _UVRSR_OK - : _UVRSR_FAILED; - case _UVRSC_WMMXD: - if (representation != _UVRSD_DOUBLE || regno > 31) - return _UVRSR_FAILED; - return unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno), - (unw_fpreg_t *)valuep) == UNW_ESUCCESS - ? _UVRSR_OK - : _UVRSR_FAILED; -#else - case _UVRSC_WMMXC: - case _UVRSC_WMMXD: - break; -#endif - } - _LIBUNWIND_ABORT("unsupported register class"); -} - -_LIBUNWIND_EXPORT _Unwind_VRS_Result -_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, - uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep) { - _Unwind_VRS_Result result = - _Unwind_VRS_Get_Internal(context, regclass, regno, representation, - valuep); - _LIBUNWIND_TRACE_API("_Unwind_VRS_Get(context=%p, regclass=%d, reg=%d, " - "rep=%d, value=0x%llX, result = %d)", - static_cast(context), regclass, regno, - representation, - ValueAsBitPattern(representation, valuep), result); - return result; -} - -_Unwind_VRS_Result -_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, - uint32_t discriminator, - _Unwind_VRS_DataRepresentation representation) { - _LIBUNWIND_TRACE_API("_Unwind_VRS_Pop(context=%p, regclass=%d, " - "discriminator=%d, representation=%d)", - static_cast(context), regclass, discriminator, - representation); - switch (regclass) { - case _UVRSC_WMMXC: -#if !defined(__ARM_WMMX) - break; -#endif - case _UVRSC_CORE: { - if (representation != _UVRSD_UINT32) - return _UVRSR_FAILED; - // When popping SP from the stack, we don't want to override it from the - // computed new stack location. See EHABI #7.5.4 table 3. - bool poppedSP = false; - uint32_t* sp; - if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, - _UVRSD_UINT32, &sp) != _UVRSR_OK) { - return _UVRSR_FAILED; - } - for (uint32_t i = 0; i < 16; ++i) { - if (!(discriminator & static_cast(1 << i))) - continue; - uint32_t value = *sp++; - if (regclass == _UVRSC_CORE && i == 13) - poppedSP = true; - if (_Unwind_VRS_Set(context, regclass, i, - _UVRSD_UINT32, &value) != _UVRSR_OK) { - return _UVRSR_FAILED; - } - } - if (!poppedSP) { - return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, - _UVRSD_UINT32, &sp); - } - return _UVRSR_OK; - } - case _UVRSC_WMMXD: -#if !defined(__ARM_WMMX) - break; -#endif - case _UVRSC_VFP: { - if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE) - return _UVRSR_FAILED; - uint32_t first = discriminator >> 16; - uint32_t count = discriminator & 0xffff; - uint32_t end = first+count; - uint32_t* sp; - if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, - _UVRSD_UINT32, &sp) != _UVRSR_OK) { - return _UVRSR_FAILED; - } - // For _UVRSD_VFPX, we're assuming the data is stored in FSTMX "standard - // format 1", which is equivalent to FSTMD + a padding word. - for (uint32_t i = first; i < end; ++i) { - // SP is only 32-bit aligned so don't copy 64-bit at a time. - uint64_t value = *sp++; - value |= ((uint64_t)(*sp++)) << 32; - if (_Unwind_VRS_Set(context, regclass, i, representation, &value) != - _UVRSR_OK) - return _UVRSR_FAILED; - } - if (representation == _UVRSD_VFPX) - ++sp; - return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp); - } - } - _LIBUNWIND_ABORT("unsupported register class"); -} - -/// Called by personality handler during phase 2 to find the start of the -/// function. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetRegionStart(struct _Unwind_Context *context) { - unw_cursor_t *cursor = (unw_cursor_t *)context; - unw_proc_info_t frameInfo; - uintptr_t result = 0; - if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) - result = (uintptr_t)frameInfo.start_ip; - _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%llX", - static_cast(context), (long long)result); - return result; -} - - -/// Called by personality handler during phase 2 if a foreign exception -// is caught. -_LIBUNWIND_EXPORT void -_Unwind_DeleteException(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)", - static_cast(exception_object)); - if (exception_object->exception_cleanup != NULL) - (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, - exception_object); -} - -extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code -__gnu_unwind_frame(_Unwind_Exception *exception_object, - struct _Unwind_Context *context) { - unw_cursor_t *cursor = (unw_cursor_t *)context; - if (unw_step(cursor) != UNW_STEP_SUCCESS) - return _URC_FAILURE; - return _URC_OK; -} - -#endif // defined(_LIBUNWIND_ARM_EHABI) Property changes on: head/contrib/llvm/projects/libunwind/src/Unwind-EHABI.cpp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/libunwind.cpp =================================================================== --- head/contrib/llvm/projects/libunwind/src/libunwind.cpp (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/libunwind.cpp (nonexistent) @@ -1,412 +0,0 @@ -//===--------------------------- libunwind.cpp ----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Implements unw_* functions from -// -//===----------------------------------------------------------------------===// - -#include - -#ifndef NDEBUG -#include // getenv -#endif -#include -#include - -#include "libunwind_ext.h" -#include "config.h" - -#include - - -#if !defined(__USING_SJLJ_EXCEPTIONS__) -#include "AddressSpace.hpp" -#include "UnwindCursor.hpp" - -using namespace libunwind; - -/// internal object to represent this processes address space -LocalAddressSpace LocalAddressSpace::sThisAddressSpace; - -_LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space = - (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace; - -/// record the registers and stack position of the caller -extern int unw_getcontext(unw_context_t *); -// note: unw_getcontext() implemented in assembly - -/// Create a cursor of a thread in this process given 'context' recorded by -/// unw_getcontext(). -_LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor, - unw_context_t *context) { - _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)", - static_cast(cursor), - static_cast(context)); -#if defined(__i386__) -# define REGISTER_KIND Registers_x86 -#elif defined(__x86_64__) -# define REGISTER_KIND Registers_x86_64 -#elif defined(__powerpc64__) -# define REGISTER_KIND Registers_ppc64 -#elif defined(__ppc__) -# define REGISTER_KIND Registers_ppc -#elif defined(__aarch64__) -# define REGISTER_KIND Registers_arm64 -#elif defined(__arm__) -# define REGISTER_KIND Registers_arm -#elif defined(__or1k__) -# define REGISTER_KIND Registers_or1k -#elif defined(__riscv) -# define REGISTER_KIND Registers_riscv -#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 -# define REGISTER_KIND Registers_mips_o32 -#elif defined(__mips64) -# define REGISTER_KIND Registers_mips_newabi -#elif defined(__mips__) -# warning The MIPS architecture is not supported with this ABI and environment! -#elif defined(__sparc__) -# define REGISTER_KIND Registers_sparc -#else -# error Architecture not supported -#endif - // Use "placement new" to allocate UnwindCursor in the cursor buffer. - new ((void *)cursor) UnwindCursor( - context, LocalAddressSpace::sThisAddressSpace); -#undef REGISTER_KIND - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - co->setInfoBasedOnIPRegister(); - - return UNW_ESUCCESS; -} - -#ifdef UNW_REMOTE -/// Create a cursor into a thread in another process. -_LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor, - unw_addr_space_t as, - void *arg) { - // special case: unw_init_remote(xx, unw_local_addr_space, xx) - if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace) - return unw_init_local(cursor, NULL); //FIXME - - // use "placement new" to allocate UnwindCursor in the cursor buffer - switch (as->cpuType) { - case CPU_TYPE_I386: - new ((void *)cursor) - UnwindCursor>, - Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg); - break; - case CPU_TYPE_X86_64: - new ((void *)cursor) - UnwindCursor>, - Registers_x86_64>(((unw_addr_space_x86_64 *)as)->oas, arg); - break; - case CPU_TYPE_POWERPC: - new ((void *)cursor) - UnwindCursor>, - Registers_ppc>(((unw_addr_space_ppc *)as)->oas, arg); - break; - default: - return UNW_EUNSPEC; - } - return UNW_ESUCCESS; -} - - -static bool is64bit(task_t task) { - return false; // FIXME -} - -/// Create an address_space object for use in examining another task. -_LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) { -#if __i386__ - if (is64bit(task)) { - unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task); - as->taskPort = task; - as->cpuType = CPU_TYPE_X86_64; - //as->oas - } else { - unw_addr_space_i386 *as = new unw_addr_space_i386(task); - as->taskPort = task; - as->cpuType = CPU_TYPE_I386; - //as->oas - } -#else -// FIXME -#endif -} - - -/// Delete an address_space object. -_LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) { - switch (asp->cpuType) { -#if __i386__ || __x86_64__ - case CPU_TYPE_I386: { - unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp; - delete as; - } - break; - case CPU_TYPE_X86_64: { - unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp; - delete as; - } - break; -#endif - case CPU_TYPE_POWERPC: { - unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp; - delete as; - } - break; - } -} -#endif // UNW_REMOTE - - -/// Get value of specified register at cursor position in stack frame. -_LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum, - unw_word_t *value) { - _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)", - static_cast(cursor), regNum, - static_cast(value)); - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - if (co->validReg(regNum)) { - *value = co->getReg(regNum); - return UNW_ESUCCESS; - } - return UNW_EBADREG; -} - - -/// Set value of specified register at cursor position in stack frame. -_LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, - unw_word_t value) { - _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%" PRIxPTR ")", - static_cast(cursor), regNum, value); - typedef LocalAddressSpace::pint_t pint_t; - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - if (co->validReg(regNum)) { - co->setReg(regNum, (pint_t)value); - // specical case altering IP to re-find info (being called by personality - // function) - if (regNum == UNW_REG_IP) { - unw_proc_info_t info; - // First, get the FDE for the old location and then update it. - co->getInfo(&info); - co->setInfoBasedOnIPRegister(false); - // If the original call expects stack adjustment, perform this now. - // Normal frame unwinding would have included the offset already in the - // CFA computation. - // Note: for PA-RISC and other platforms where the stack grows up, - // this should actually be - info.gp. LLVM doesn't currently support - // any such platforms and Clang doesn't export a macro for them. - if (info.gp) - co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp); - } - return UNW_ESUCCESS; - } - return UNW_EBADREG; -} - - -/// Get value of specified float register at cursor position in stack frame. -_LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, - unw_fpreg_t *value) { - _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)", - static_cast(cursor), regNum, - static_cast(value)); - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - if (co->validFloatReg(regNum)) { - *value = co->getFloatReg(regNum); - return UNW_ESUCCESS; - } - return UNW_EBADREG; -} - - -/// Set value of specified float register at cursor position in stack frame. -_LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, - unw_fpreg_t value) { -#if defined(_LIBUNWIND_ARM_EHABI) - _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)", - static_cast(cursor), regNum, value); -#else - _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)", - static_cast(cursor), regNum, value); -#endif - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - if (co->validFloatReg(regNum)) { - co->setFloatReg(regNum, value); - return UNW_ESUCCESS; - } - return UNW_EBADREG; -} - - -/// Move cursor to next frame. -_LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_step(cursor=%p)", static_cast(cursor)); - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - return co->step(); -} - - -/// Get unwind info at cursor position in stack frame. -_LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor, - unw_proc_info_t *info) { - _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)", - static_cast(cursor), static_cast(info)); - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - co->getInfo(info); - if (info->end_ip == 0) - return UNW_ENOINFO; - else - return UNW_ESUCCESS; -} - - -/// Resume execution at cursor position (aka longjump). -_LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)", static_cast(cursor)); - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - co->jumpto(); - return UNW_EUNSPEC; -} - - -/// Get name of function at cursor position in stack frame. -_LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf, - size_t bufLen, unw_word_t *offset) { - _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)", - static_cast(cursor), static_cast(buf), - static_cast(bufLen)); - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - if (co->getFunctionName(buf, bufLen, offset)) - return UNW_ESUCCESS; - else - return UNW_EUNSPEC; -} - - -/// Checks if a register is a floating-point register. -_LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) { - _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)", - static_cast(cursor), regNum); - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - return co->validFloatReg(regNum); -} - - -/// Checks if a register is a floating-point register. -_LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor, - unw_regnum_t regNum) { - _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)", - static_cast(cursor), regNum); - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - return co->getRegisterName(regNum); -} - - -/// Checks if current frame is signal trampoline. -_LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)", - static_cast(cursor)); - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - return co->isSignalFrame(); -} - -#ifdef __arm__ -// Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD -_LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)", - static_cast(cursor)); - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - return co->saveVFPAsX(); -} -#endif - - -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) -/// SPI: walks cached DWARF entries -_LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)( - unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { - _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)", - reinterpret_cast(func)); - DwarfFDECache::iterateCacheEntries(func); -} - - -/// IPI: for __register_frame() -void _unw_add_dynamic_fde(unw_word_t fde) { - CFI_Parser::FDE_Info fdeInfo; - CFI_Parser::CIE_Info cieInfo; - const char *message = CFI_Parser::decodeFDE( - LocalAddressSpace::sThisAddressSpace, - (LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo); - if (message == NULL) { - // dynamically registered FDEs don't have a mach_header group they are in. - // Use fde as mh_group - unw_word_t mh_group = fdeInfo.fdeStart; - DwarfFDECache::add((LocalAddressSpace::pint_t)mh_group, - fdeInfo.pcStart, fdeInfo.pcEnd, - fdeInfo.fdeStart); - } else { - _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message); - } -} - -/// IPI: for __deregister_frame() -void _unw_remove_dynamic_fde(unw_word_t fde) { - // fde is own mh_group - DwarfFDECache::removeAllIn((LocalAddressSpace::pint_t)fde); -} -#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) -#endif // !defined(__USING_SJLJ_EXCEPTIONS__) - - - -// Add logging hooks in Debug builds only -#ifndef NDEBUG -#include - -_LIBUNWIND_HIDDEN -bool logAPIs() { - // do manual lock to avoid use of _cxa_guard_acquire or initializers - static bool checked = false; - static bool log = false; - if (!checked) { - log = (getenv("LIBUNWIND_PRINT_APIS") != NULL); - checked = true; - } - return log; -} - -_LIBUNWIND_HIDDEN -bool logUnwinding() { - // do manual lock to avoid use of _cxa_guard_acquire or initializers - static bool checked = false; - static bool log = false; - if (!checked) { - log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL); - checked = true; - } - return log; -} - -_LIBUNWIND_HIDDEN -bool logDWARF() { - // do manual lock to avoid use of _cxa_guard_acquire or initializers - static bool checked = false; - static bool log = false; - if (!checked) { - log = (getenv("LIBUNWIND_PRINT_DWARF") != NULL); - checked = true; - } - return log; -} - -#endif // NDEBUG - Property changes on: head/contrib/llvm/projects/libunwind/src/libunwind.cpp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/UnwindLevel1-gcc-ext.c =================================================================== --- head/contrib/llvm/projects/libunwind/src/UnwindLevel1-gcc-ext.c (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/UnwindLevel1-gcc-ext.c (nonexistent) @@ -1,362 +0,0 @@ -//===--------------------- UnwindLevel1-gcc-ext.c -------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Implements gcc extensions to the C++ ABI Exception Handling Level 1. -// -//===----------------------------------------------------------------------===// - -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "libunwind_ext.h" -#include "libunwind.h" -#include "Unwind-EHABI.h" -#include "unwind.h" - -#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) - -#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) -#define private_1 private_[0] -#endif - -/// Called by __cxa_rethrow(). -_LIBUNWIND_EXPORT _Unwind_Reason_Code -_Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) { -#if defined(_LIBUNWIND_ARM_EHABI) - _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld", - (void *)exception_object, - (long)exception_object->unwinder_cache.reserved1); -#else - _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%" PRIdPTR, - (void *)exception_object, - (intptr_t)exception_object->private_1); -#endif - -#if defined(_LIBUNWIND_ARM_EHABI) - // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0, - // which is in the same position as private_1 below. - return _Unwind_RaiseException(exception_object); -#else - // If this is non-forced and a stopping place was found, then this is a - // re-throw. - // Call _Unwind_RaiseException() as if this was a new exception - if (exception_object->private_1 == 0) { - return _Unwind_RaiseException(exception_object); - // Will return if there is no catch clause, so that __cxa_rethrow can call - // std::terminate(). - } - - // Call through to _Unwind_Resume() which distiguishes between forced and - // regular exceptions. - _Unwind_Resume(exception_object); - _LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()" - " which unexpectedly returned"); -#endif -} - - -/// Called by personality handler during phase 2 to get base address for data -/// relative encodings. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetDataRelBase(struct _Unwind_Context *context) { - (void)context; - _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context); - _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented"); -} - - -/// Called by personality handler during phase 2 to get base address for text -/// relative encodings. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetTextRelBase(struct _Unwind_Context *context) { - (void)context; - _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", (void *)context); - _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented"); -} - - -/// Scans unwind information to find the function that contains the -/// specified code address "pc". -_LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) { - _LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)", pc); - // This is slow, but works. - // We create an unwind cursor then alter the IP to be pc - unw_cursor_t cursor; - unw_context_t uc; - unw_proc_info_t info; - unw_getcontext(&uc); - unw_init_local(&cursor, &uc); - unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t) pc); - if (unw_get_proc_info(&cursor, &info) == UNW_ESUCCESS) - return (void *)(intptr_t) info.start_ip; - else - return NULL; -} - -/// Walk every frame and call trace function at each one. If trace function -/// returns anything other than _URC_NO_REASON, then walk is terminated. -_LIBUNWIND_EXPORT _Unwind_Reason_Code -_Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { - unw_cursor_t cursor; - unw_context_t uc; - unw_getcontext(&uc); - unw_init_local(&cursor, &uc); - - _LIBUNWIND_TRACE_API("_Unwind_Backtrace(callback=%p)", - (void *)(uintptr_t)callback); - -#if defined(_LIBUNWIND_ARM_EHABI) - // Create a mock exception object for force unwinding. - _Unwind_Exception ex; - memset(&ex, '\0', sizeof(ex)); - ex.exception_class = 0x434C4E47554E5700; // CLNGUNW\0 -#endif - - // walk each frame - while (true) { - _Unwind_Reason_Code result; - -#if !defined(_LIBUNWIND_ARM_EHABI) - // ask libunwind to get next frame (skip over first frame which is - // _Unwind_Backtrace()) - if (unw_step(&cursor) <= 0) { - _LIBUNWIND_TRACE_UNWINDING(" _backtrace: ended because cursor reached " - "bottom of stack, returning %d", - _URC_END_OF_STACK); - return _URC_END_OF_STACK; - } -#else - // Get the information for this frame. - unw_proc_info_t frameInfo; - if (unw_get_proc_info(&cursor, &frameInfo) != UNW_ESUCCESS) { - return _URC_END_OF_STACK; - } - - // Update the pr_cache in the mock exception object. - const uint32_t* unwindInfo = (uint32_t *) frameInfo.unwind_info; - ex.pr_cache.fnstart = frameInfo.start_ip; - ex.pr_cache.ehtp = (_Unwind_EHT_Header *) unwindInfo; - ex.pr_cache.additional= frameInfo.flags; - - struct _Unwind_Context *context = (struct _Unwind_Context *)&cursor; - // Get and call the personality function to unwind the frame. - __personality_routine handler = (__personality_routine) frameInfo.handler; - if (handler == NULL) { - return _URC_END_OF_STACK; - } - if (handler(_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, &ex, context) != - _URC_CONTINUE_UNWIND) { - return _URC_END_OF_STACK; - } -#endif // defined(_LIBUNWIND_ARM_EHABI) - - // debugging - if (_LIBUNWIND_TRACING_UNWINDING) { - char functionName[512]; - unw_proc_info_t frame; - unw_word_t offset; - unw_get_proc_name(&cursor, functionName, 512, &offset); - unw_get_proc_info(&cursor, &frame); - _LIBUNWIND_TRACE_UNWINDING( - " _backtrace: start_ip=0x%" PRIxPTR ", func=%s, lsda=0x%" PRIxPTR ", context=%p", - frame.start_ip, functionName, frame.lsda, - (void *)&cursor); - } - - // call trace function with this frame - result = (*callback)((struct _Unwind_Context *)(&cursor), ref); - if (result != _URC_NO_REASON) { - _LIBUNWIND_TRACE_UNWINDING( - " _backtrace: ended because callback returned %d", result); - return result; - } - } -} - - -/// Find DWARF unwind info for an address 'pc' in some function. -_LIBUNWIND_EXPORT const void *_Unwind_Find_FDE(const void *pc, - struct dwarf_eh_bases *bases) { - // This is slow, but works. - // We create an unwind cursor then alter the IP to be pc - unw_cursor_t cursor; - unw_context_t uc; - unw_proc_info_t info; - unw_getcontext(&uc); - unw_init_local(&cursor, &uc); - unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t) pc); - unw_get_proc_info(&cursor, &info); - bases->tbase = (uintptr_t)info.extra; - bases->dbase = 0; // dbase not used on Mac OS X - bases->func = (uintptr_t)info.start_ip; - _LIBUNWIND_TRACE_API("_Unwind_Find_FDE(pc=%p) => %p", pc, - (void *)(intptr_t) info.unwind_info); - return (void *)(intptr_t) info.unwind_info; -} - -/// Returns the CFA (call frame area, or stack pointer at start of function) -/// for the current context. -_LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { - unw_cursor_t *cursor = (unw_cursor_t *)context; - unw_word_t result; - unw_get_reg(cursor, UNW_REG_SP, &result); - _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p) => 0x%" PRIxPTR, - (void *)context, result); - return (uintptr_t)result; -} - - -/// Called by personality handler during phase 2 to get instruction pointer. -/// ipBefore is a boolean that says if IP is already adjusted to be the call -/// site address. Normally IP is the return address. -_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, - int *ipBefore) { - _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p)", (void *)context); - *ipBefore = 0; - return _Unwind_GetIP(context); -} - -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - -#ifdef __FreeBSD__ - -// Based on LLVM's lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp -// and XXX should be fixed to be alignment-safe. -static void processFDE(const char *addr, bool isDeregister) { - uint64_t length; - while ((length = *((const uint32_t *)addr)) != 0) { - const char *p = addr + 4; - if (length == 0xffffffff) { - length = *((const uint64_t *)p); - p += 8; - } - uint32_t offset = *((const uint32_t *)p); - if (offset != 0) { - if (isDeregister) - _unw_remove_dynamic_fde((unw_word_t)(uintptr_t)addr); - else - _unw_add_dynamic_fde((unw_word_t)(uintptr_t)addr); - } - addr = p + length; - } -} - -/// Called by programs with dynamic code generators that want to register -/// dynamically generated FDEs, with a libgcc-compatible API. - -_LIBUNWIND_EXPORT void __register_frame(const void *addr) { - _LIBUNWIND_TRACE_API("__register_frame(%p)", addr); - processFDE(addr, false); -} - -/// Called by programs with dynamic code generators that want to unregister -/// dynamically generated FDEs, with a libgcc-compatible API. -_LIBUNWIND_EXPORT void __deregister_frame(const void *addr) { - _LIBUNWIND_TRACE_API("__deregister_frame(%p)", addr); - processFDE(addr, true); -} - - -#else - -/// Called by programs with dynamic code generators that want -/// to register a dynamically generated FDE. -/// This function has existed on Mac OS X since 10.4, but -/// was broken until 10.6. -_LIBUNWIND_EXPORT void __register_frame(const void *fde) { - _LIBUNWIND_TRACE_API("__register_frame(%p)", fde); - _unw_add_dynamic_fde((unw_word_t)(uintptr_t) fde); -} - - -/// Called by programs with dynamic code generators that want -/// to unregister a dynamically generated FDE. -/// This function has existed on Mac OS X since 10.4, but -/// was broken until 10.6. -_LIBUNWIND_EXPORT void __deregister_frame(const void *fde) { - _LIBUNWIND_TRACE_API("__deregister_frame(%p)", fde); - _unw_remove_dynamic_fde((unw_word_t)(uintptr_t) fde); -} - -#endif - -// The following register/deregister functions are gcc extensions. -// They have existed on Mac OS X, but have never worked because Mac OS X -// before 10.6 used keymgr to track known FDEs, but these functions -// never got updated to use keymgr. -// For now, we implement these as do-nothing functions to keep any existing -// applications working. We also add the not in 10.6 symbol so that nwe -// application won't be able to use them. - -#if defined(_LIBUNWIND_SUPPORT_FRAME_APIS) -_LIBUNWIND_EXPORT void __register_frame_info_bases(const void *fde, void *ob, - void *tb, void *db) { - (void)fde; - (void)ob; - (void)tb; - (void)db; - _LIBUNWIND_TRACE_API("__register_frame_info_bases(%p,%p, %p, %p)", - fde, ob, tb, db); - // do nothing, this function never worked in Mac OS X -} - -_LIBUNWIND_EXPORT void __register_frame_info(const void *fde, void *ob) { - (void)fde; - (void)ob; - _LIBUNWIND_TRACE_API("__register_frame_info(%p, %p)", fde, ob); - // do nothing, this function never worked in Mac OS X -} - -_LIBUNWIND_EXPORT void __register_frame_info_table_bases(const void *fde, - void *ob, void *tb, - void *db) { - (void)fde; - (void)ob; - (void)tb; - (void)db; - _LIBUNWIND_TRACE_API("__register_frame_info_table_bases" - "(%p,%p, %p, %p)", fde, ob, tb, db); - // do nothing, this function never worked in Mac OS X -} - -_LIBUNWIND_EXPORT void __register_frame_info_table(const void *fde, void *ob) { - (void)fde; - (void)ob; - _LIBUNWIND_TRACE_API("__register_frame_info_table(%p, %p)", fde, ob); - // do nothing, this function never worked in Mac OS X -} - -_LIBUNWIND_EXPORT void __register_frame_table(const void *fde) { - (void)fde; - _LIBUNWIND_TRACE_API("__register_frame_table(%p)", fde); - // do nothing, this function never worked in Mac OS X -} - -_LIBUNWIND_EXPORT void *__deregister_frame_info(const void *fde) { - (void)fde; - _LIBUNWIND_TRACE_API("__deregister_frame_info(%p)", fde); - // do nothing, this function never worked in Mac OS X - return NULL; -} - -_LIBUNWIND_EXPORT void *__deregister_frame_info_bases(const void *fde) { - (void)fde; - _LIBUNWIND_TRACE_API("__deregister_frame_info_bases(%p)", fde); - // do nothing, this function never worked in Mac OS X - return NULL; -} -#endif // defined(_LIBUNWIND_SUPPORT_FRAME_APIS) - -#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - -#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) Property changes on: head/contrib/llvm/projects/libunwind/src/UnwindLevel1-gcc-ext.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/Unwind_AppleExtras.cpp =================================================================== --- head/contrib/llvm/projects/libunwind/src/Unwind_AppleExtras.cpp (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/Unwind_AppleExtras.cpp (nonexistent) @@ -1,184 +0,0 @@ -//===--------------------- Unwind_AppleExtras.cpp -------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -//===----------------------------------------------------------------------===// - -#include "config.h" -#include "AddressSpace.hpp" -#include "DwarfParser.hpp" - - -// private keymgr stuff -#define KEYMGR_GCC3_DW2_OBJ_LIST 302 -extern "C" { - extern void _keymgr_set_and_unlock_processwide_ptr(int key, void *ptr); - extern void *_keymgr_get_and_lock_processwide_ptr(int key); -} - -// undocumented libgcc "struct object" -struct libgcc_object { - void *start; - void *unused1; - void *unused2; - void *fde; - unsigned long encoding; - void *fde_end; - libgcc_object *next; -}; - -// undocumented libgcc "struct km_object_info" referenced by -// KEYMGR_GCC3_DW2_OBJ_LIST -struct libgcc_object_info { - libgcc_object *seen_objects; - libgcc_object *unseen_objects; - unsigned spare[2]; -}; - - -// static linker symbols to prevent wrong two level namespace for _Unwind symbols -#if defined(__arm__) - #define NOT_HERE_BEFORE_5_0(sym) \ - extern const char sym##_tmp30 __asm("$ld$hide$os3.0$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp30 = 0; \ - extern const char sym##_tmp31 __asm("$ld$hide$os3.1$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp31 = 0; \ - extern const char sym##_tmp32 __asm("$ld$hide$os3.2$_" #sym );\ - __attribute__((visibility("default"))) const char sym##_tmp32 = 0; \ - extern const char sym##_tmp40 __asm("$ld$hide$os4.0$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp40 = 0; \ - extern const char sym##_tmp41 __asm("$ld$hide$os4.1$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp41 = 0; \ - extern const char sym##_tmp42 __asm("$ld$hide$os4.2$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp42 = 0; \ - extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp43 = 0; -#elif defined(__arm64__) - #define NOT_HERE_BEFORE_10_6(sym) - #define NEVER_HERE(sym) -#else - #define NOT_HERE_BEFORE_10_6(sym) \ - extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \ - extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp5 = 0; - #define NEVER_HERE(sym) \ - extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \ - extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \ - extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp6 = 0; -#endif - - -#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) - -// -// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in -// earlier versions -// -NOT_HERE_BEFORE_10_6(_Unwind_DeleteException) -NOT_HERE_BEFORE_10_6(_Unwind_Find_FDE) -NOT_HERE_BEFORE_10_6(_Unwind_ForcedUnwind) -NOT_HERE_BEFORE_10_6(_Unwind_GetGR) -NOT_HERE_BEFORE_10_6(_Unwind_GetIP) -NOT_HERE_BEFORE_10_6(_Unwind_GetLanguageSpecificData) -NOT_HERE_BEFORE_10_6(_Unwind_GetRegionStart) -NOT_HERE_BEFORE_10_6(_Unwind_RaiseException) -NOT_HERE_BEFORE_10_6(_Unwind_Resume) -NOT_HERE_BEFORE_10_6(_Unwind_SetGR) -NOT_HERE_BEFORE_10_6(_Unwind_SetIP) -NOT_HERE_BEFORE_10_6(_Unwind_Backtrace) -NOT_HERE_BEFORE_10_6(_Unwind_FindEnclosingFunction) -NOT_HERE_BEFORE_10_6(_Unwind_GetCFA) -NOT_HERE_BEFORE_10_6(_Unwind_GetDataRelBase) -NOT_HERE_BEFORE_10_6(_Unwind_GetTextRelBase) -NOT_HERE_BEFORE_10_6(_Unwind_Resume_or_Rethrow) -NOT_HERE_BEFORE_10_6(_Unwind_GetIPInfo) -NOT_HERE_BEFORE_10_6(__register_frame) -NOT_HERE_BEFORE_10_6(__deregister_frame) - -// -// symbols in libSystem.dylib for compatibility, but we don't want any new code -// using them -// -NEVER_HERE(__register_frame_info_bases) -NEVER_HERE(__register_frame_info) -NEVER_HERE(__register_frame_info_table_bases) -NEVER_HERE(__register_frame_info_table) -NEVER_HERE(__register_frame_table) -NEVER_HERE(__deregister_frame_info) -NEVER_HERE(__deregister_frame_info_bases) - -#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) - - - - -#if defined(_LIBUNWIND_BUILD_SJLJ_APIS) -// -// symbols in libSystem.dylib in iOS 5.0 and later, but are in libgcc_s.dylib in -// earlier versions -// -NOT_HERE_BEFORE_5_0(_Unwind_GetLanguageSpecificData) -NOT_HERE_BEFORE_5_0(_Unwind_GetRegionStart) -NOT_HERE_BEFORE_5_0(_Unwind_GetIP) -NOT_HERE_BEFORE_5_0(_Unwind_SetGR) -NOT_HERE_BEFORE_5_0(_Unwind_SetIP) -NOT_HERE_BEFORE_5_0(_Unwind_DeleteException) -NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Register) -NOT_HERE_BEFORE_5_0(_Unwind_GetGR) -NOT_HERE_BEFORE_5_0(_Unwind_GetIPInfo) -NOT_HERE_BEFORE_5_0(_Unwind_GetCFA) -NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume) -NOT_HERE_BEFORE_5_0(_Unwind_SjLj_RaiseException) -NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow) -NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister) - -#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS) - - -namespace libunwind { - -_LIBUNWIND_HIDDEN -bool checkKeyMgrRegisteredFDEs(uintptr_t pc, void *&fde) { -#if __MAC_OS_X_VERSION_MIN_REQUIRED - // lastly check for old style keymgr registration of dynamically generated - // FDEs acquire exclusive access to libgcc_object_info - libgcc_object_info *head = (libgcc_object_info *) - _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST); - if (head != NULL) { - // look at each FDE in keymgr - for (libgcc_object *ob = head->unseen_objects; ob != NULL; ob = ob->next) { - CFI_Parser::FDE_Info fdeInfo; - CFI_Parser::CIE_Info cieInfo; - const char *msg = CFI_Parser::decodeFDE( - LocalAddressSpace::sThisAddressSpace, - (uintptr_t)ob->fde, &fdeInfo, &cieInfo); - if (msg == NULL) { - // Check if this FDE is for a function that includes the pc - if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) { - fde = (void*)fdeInfo.pcStart; - _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, - head); - return true; - } - } - } - } - // release libgcc_object_info - _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head); -#else - (void)pc; - (void)fde; -#endif - return false; -} - -} - Property changes on: head/contrib/llvm/projects/libunwind/src/Unwind_AppleExtras.cpp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/UnwindRegistersSave.S =================================================================== --- head/contrib/llvm/projects/libunwind/src/UnwindRegistersSave.S (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/UnwindRegistersSave.S (nonexistent) @@ -1,1058 +0,0 @@ -//===------------------------ UnwindRegistersSave.S -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "assembly.h" - - .text - -#if !defined(__USING_SJLJ_EXCEPTIONS__) - -#if defined(__i386__) - -# -# extern int unw_getcontext(unw_context_t* thread_state) -# -# On entry: -# + + -# +-----------------------+ -# + thread_state pointer + -# +-----------------------+ -# + return address + -# +-----------------------+ <-- SP -# + + -# -DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - push %eax - movl 8(%esp), %eax - movl %ebx, 4(%eax) - movl %ecx, 8(%eax) - movl %edx, 12(%eax) - movl %edi, 16(%eax) - movl %esi, 20(%eax) - movl %ebp, 24(%eax) - movl %esp, %edx - addl $8, %edx - movl %edx, 28(%eax) # store what sp was at call site as esp - # skip ss - # skip eflags - movl 4(%esp), %edx - movl %edx, 40(%eax) # store return address as eip - # skip cs - # skip ds - # skip es - # skip fs - # skip gs - movl (%esp), %edx - movl %edx, (%eax) # store original eax - popl %eax - xorl %eax, %eax # return UNW_ESUCCESS - ret - -#elif defined(__x86_64__) - -# -# extern int unw_getcontext(unw_context_t* thread_state) -# -# On entry: -# thread_state pointer is in rdi -# -DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) -#if defined(_WIN64) -#define PTR %rcx -#define TMP %rdx -#else -#define PTR %rdi -#define TMP %rsi -#endif - - movq %rax, (PTR) - movq %rbx, 8(PTR) - movq %rcx, 16(PTR) - movq %rdx, 24(PTR) - movq %rdi, 32(PTR) - movq %rsi, 40(PTR) - movq %rbp, 48(PTR) - movq %rsp, 56(PTR) - addq $8, 56(PTR) - movq %r8, 64(PTR) - movq %r9, 72(PTR) - movq %r10, 80(PTR) - movq %r11, 88(PTR) - movq %r12, 96(PTR) - movq %r13,104(PTR) - movq %r14,112(PTR) - movq %r15,120(PTR) - movq (%rsp),TMP - movq TMP,128(PTR) # store return address as rip - # skip rflags - # skip cs - # skip fs - # skip gs - -#if defined(_WIN64) - movdqu %xmm0,176(PTR) - movdqu %xmm1,192(PTR) - movdqu %xmm2,208(PTR) - movdqu %xmm3,224(PTR) - movdqu %xmm4,240(PTR) - movdqu %xmm5,256(PTR) - movdqu %xmm6,272(PTR) - movdqu %xmm7,288(PTR) - movdqu %xmm8,304(PTR) - movdqu %xmm9,320(PTR) - movdqu %xmm10,336(PTR) - movdqu %xmm11,352(PTR) - movdqu %xmm12,368(PTR) - movdqu %xmm13,384(PTR) - movdqu %xmm14,400(PTR) - movdqu %xmm15,416(PTR) -#endif - xorl %eax, %eax # return UNW_ESUCCESS - ret - -#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 - -# -# extern int unw_getcontext(unw_context_t* thread_state) -# -# On entry: -# thread_state pointer is in a0 ($4) -# -DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - .set push - .set noat - .set noreorder - .set nomacro - sw $1, (4 * 1)($4) - sw $2, (4 * 2)($4) - sw $3, (4 * 3)($4) - sw $4, (4 * 4)($4) - sw $5, (4 * 5)($4) - sw $6, (4 * 6)($4) - sw $7, (4 * 7)($4) - sw $8, (4 * 8)($4) - sw $9, (4 * 9)($4) - sw $10, (4 * 10)($4) - sw $11, (4 * 11)($4) - sw $12, (4 * 12)($4) - sw $13, (4 * 13)($4) - sw $14, (4 * 14)($4) - sw $15, (4 * 15)($4) - sw $16, (4 * 16)($4) - sw $17, (4 * 17)($4) - sw $18, (4 * 18)($4) - sw $19, (4 * 19)($4) - sw $20, (4 * 20)($4) - sw $21, (4 * 21)($4) - sw $22, (4 * 22)($4) - sw $23, (4 * 23)($4) - sw $24, (4 * 24)($4) - sw $25, (4 * 25)($4) - sw $26, (4 * 26)($4) - sw $27, (4 * 27)($4) - sw $28, (4 * 28)($4) - sw $29, (4 * 29)($4) - sw $30, (4 * 30)($4) - sw $31, (4 * 31)($4) - # Store return address to pc - sw $31, (4 * 32)($4) - # hi and lo - mfhi $8 - sw $8, (4 * 33)($4) - mflo $8 - sw $8, (4 * 34)($4) -#ifdef __mips_hard_float -#if __mips_fpr != 64 - sdc1 $f0, (4 * 36 + 8 * 0)($4) - sdc1 $f2, (4 * 36 + 8 * 2)($4) - sdc1 $f4, (4 * 36 + 8 * 4)($4) - sdc1 $f6, (4 * 36 + 8 * 6)($4) - sdc1 $f8, (4 * 36 + 8 * 8)($4) - sdc1 $f10, (4 * 36 + 8 * 10)($4) - sdc1 $f12, (4 * 36 + 8 * 12)($4) - sdc1 $f14, (4 * 36 + 8 * 14)($4) - sdc1 $f16, (4 * 36 + 8 * 16)($4) - sdc1 $f18, (4 * 36 + 8 * 18)($4) - sdc1 $f20, (4 * 36 + 8 * 20)($4) - sdc1 $f22, (4 * 36 + 8 * 22)($4) - sdc1 $f24, (4 * 36 + 8 * 24)($4) - sdc1 $f26, (4 * 36 + 8 * 26)($4) - sdc1 $f28, (4 * 36 + 8 * 28)($4) - sdc1 $f30, (4 * 36 + 8 * 30)($4) -#else - sdc1 $f0, (4 * 36 + 8 * 0)($4) - sdc1 $f1, (4 * 36 + 8 * 1)($4) - sdc1 $f2, (4 * 36 + 8 * 2)($4) - sdc1 $f3, (4 * 36 + 8 * 3)($4) - sdc1 $f4, (4 * 36 + 8 * 4)($4) - sdc1 $f5, (4 * 36 + 8 * 5)($4) - sdc1 $f6, (4 * 36 + 8 * 6)($4) - sdc1 $f7, (4 * 36 + 8 * 7)($4) - sdc1 $f8, (4 * 36 + 8 * 8)($4) - sdc1 $f9, (4 * 36 + 8 * 9)($4) - sdc1 $f10, (4 * 36 + 8 * 10)($4) - sdc1 $f11, (4 * 36 + 8 * 11)($4) - sdc1 $f12, (4 * 36 + 8 * 12)($4) - sdc1 $f13, (4 * 36 + 8 * 13)($4) - sdc1 $f14, (4 * 36 + 8 * 14)($4) - sdc1 $f15, (4 * 36 + 8 * 15)($4) - sdc1 $f16, (4 * 36 + 8 * 16)($4) - sdc1 $f17, (4 * 36 + 8 * 17)($4) - sdc1 $f18, (4 * 36 + 8 * 18)($4) - sdc1 $f19, (4 * 36 + 8 * 19)($4) - sdc1 $f20, (4 * 36 + 8 * 20)($4) - sdc1 $f21, (4 * 36 + 8 * 21)($4) - sdc1 $f22, (4 * 36 + 8 * 22)($4) - sdc1 $f23, (4 * 36 + 8 * 23)($4) - sdc1 $f24, (4 * 36 + 8 * 24)($4) - sdc1 $f25, (4 * 36 + 8 * 25)($4) - sdc1 $f26, (4 * 36 + 8 * 26)($4) - sdc1 $f27, (4 * 36 + 8 * 27)($4) - sdc1 $f28, (4 * 36 + 8 * 28)($4) - sdc1 $f29, (4 * 36 + 8 * 29)($4) - sdc1 $f30, (4 * 36 + 8 * 30)($4) - sdc1 $f31, (4 * 36 + 8 * 31)($4) -#endif -#endif - jr $31 - # return UNW_ESUCCESS - or $2, $0, $0 - .set pop - -#elif defined(__mips64) - -# -# extern int unw_getcontext(unw_context_t* thread_state) -# -# On entry: -# thread_state pointer is in a0 ($4) -# -DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - .set push - .set noat - .set noreorder - .set nomacro - sd $1, (8 * 1)($4) - sd $2, (8 * 2)($4) - sd $3, (8 * 3)($4) - sd $4, (8 * 4)($4) - sd $5, (8 * 5)($4) - sd $6, (8 * 6)($4) - sd $7, (8 * 7)($4) - sd $8, (8 * 8)($4) - sd $9, (8 * 9)($4) - sd $10, (8 * 10)($4) - sd $11, (8 * 11)($4) - sd $12, (8 * 12)($4) - sd $13, (8 * 13)($4) - sd $14, (8 * 14)($4) - sd $15, (8 * 15)($4) - sd $16, (8 * 16)($4) - sd $17, (8 * 17)($4) - sd $18, (8 * 18)($4) - sd $19, (8 * 19)($4) - sd $20, (8 * 20)($4) - sd $21, (8 * 21)($4) - sd $22, (8 * 22)($4) - sd $23, (8 * 23)($4) - sd $24, (8 * 24)($4) - sd $25, (8 * 25)($4) - sd $26, (8 * 26)($4) - sd $27, (8 * 27)($4) - sd $28, (8 * 28)($4) - sd $29, (8 * 29)($4) - sd $30, (8 * 30)($4) - sd $31, (8 * 31)($4) - # Store return address to pc - sd $31, (8 * 32)($4) - # hi and lo - mfhi $8 - sd $8, (8 * 33)($4) - mflo $8 - sd $8, (8 * 34)($4) -#ifdef __mips_hard_float - sdc1 $f0, (8 * 35)($4) - sdc1 $f1, (8 * 36)($4) - sdc1 $f2, (8 * 37)($4) - sdc1 $f3, (8 * 38)($4) - sdc1 $f4, (8 * 39)($4) - sdc1 $f5, (8 * 40)($4) - sdc1 $f6, (8 * 41)($4) - sdc1 $f7, (8 * 42)($4) - sdc1 $f8, (8 * 43)($4) - sdc1 $f9, (8 * 44)($4) - sdc1 $f10, (8 * 45)($4) - sdc1 $f11, (8 * 46)($4) - sdc1 $f12, (8 * 47)($4) - sdc1 $f13, (8 * 48)($4) - sdc1 $f14, (8 * 49)($4) - sdc1 $f15, (8 * 50)($4) - sdc1 $f16, (8 * 51)($4) - sdc1 $f17, (8 * 52)($4) - sdc1 $f18, (8 * 53)($4) - sdc1 $f19, (8 * 54)($4) - sdc1 $f20, (8 * 55)($4) - sdc1 $f21, (8 * 56)($4) - sdc1 $f22, (8 * 57)($4) - sdc1 $f23, (8 * 58)($4) - sdc1 $f24, (8 * 59)($4) - sdc1 $f25, (8 * 60)($4) - sdc1 $f26, (8 * 61)($4) - sdc1 $f27, (8 * 62)($4) - sdc1 $f28, (8 * 63)($4) - sdc1 $f29, (8 * 64)($4) - sdc1 $f30, (8 * 65)($4) - sdc1 $f31, (8 * 66)($4) -#endif - jr $31 - # return UNW_ESUCCESS - or $2, $0, $0 - .set pop - -# elif defined(__mips__) - -# -# extern int unw_getcontext(unw_context_t* thread_state) -# -# Just trap for the time being. -DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - teq $0, $0 - -#elif defined(__powerpc64__) - -// -// extern int unw_getcontext(unw_context_t* thread_state) -// -// On entry: -// thread_state pointer is in r3 -// -DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - -// store register (GPR) -#define PPC64_STR(n) \ - std %r##n, (8 * (n + 2))(%r3) - - // save GPRs - PPC64_STR(0) - mflr %r0 - std %r0, PPC64_OFFS_SRR0(%r3) // store lr as ssr0 - PPC64_STR(1) - PPC64_STR(2) - PPC64_STR(3) - PPC64_STR(4) - PPC64_STR(5) - PPC64_STR(6) - PPC64_STR(7) - PPC64_STR(8) - PPC64_STR(9) - PPC64_STR(10) - PPC64_STR(11) - PPC64_STR(12) - PPC64_STR(13) - PPC64_STR(14) - PPC64_STR(15) - PPC64_STR(16) - PPC64_STR(17) - PPC64_STR(18) - PPC64_STR(19) - PPC64_STR(20) - PPC64_STR(21) - PPC64_STR(22) - PPC64_STR(23) - PPC64_STR(24) - PPC64_STR(25) - PPC64_STR(26) - PPC64_STR(27) - PPC64_STR(28) - PPC64_STR(29) - PPC64_STR(30) - PPC64_STR(31) - - mfcr %r0 - std %r0, PPC64_OFFS_CR(%r3) - mfxer %r0 - std %r0, PPC64_OFFS_XER(%r3) - mflr %r0 - std %r0, PPC64_OFFS_LR(%r3) - mfctr %r0 - std %r0, PPC64_OFFS_CTR(%r3) - mfvrsave %r0 - std %r0, PPC64_OFFS_VRSAVE(%r3) - -#ifdef PPC64_HAS_VMX - // save VS registers - // (note that this also saves floating point registers and V registers, - // because part of VS is mapped to these registers) - - addi %r4, %r3, PPC64_OFFS_FP - -// store VS register -#define PPC64_STVS(n) \ - stxvd2x %vs##n, 0, %r4 ;\ - addi %r4, %r4, 16 - - PPC64_STVS(0) - PPC64_STVS(1) - PPC64_STVS(2) - PPC64_STVS(3) - PPC64_STVS(4) - PPC64_STVS(5) - PPC64_STVS(6) - PPC64_STVS(7) - PPC64_STVS(8) - PPC64_STVS(9) - PPC64_STVS(10) - PPC64_STVS(11) - PPC64_STVS(12) - PPC64_STVS(13) - PPC64_STVS(14) - PPC64_STVS(15) - PPC64_STVS(16) - PPC64_STVS(17) - PPC64_STVS(18) - PPC64_STVS(19) - PPC64_STVS(20) - PPC64_STVS(21) - PPC64_STVS(22) - PPC64_STVS(23) - PPC64_STVS(24) - PPC64_STVS(25) - PPC64_STVS(26) - PPC64_STVS(27) - PPC64_STVS(28) - PPC64_STVS(29) - PPC64_STVS(30) - PPC64_STVS(31) - PPC64_STVS(32) - PPC64_STVS(33) - PPC64_STVS(34) - PPC64_STVS(35) - PPC64_STVS(36) - PPC64_STVS(37) - PPC64_STVS(38) - PPC64_STVS(39) - PPC64_STVS(40) - PPC64_STVS(41) - PPC64_STVS(42) - PPC64_STVS(43) - PPC64_STVS(44) - PPC64_STVS(45) - PPC64_STVS(46) - PPC64_STVS(47) - PPC64_STVS(48) - PPC64_STVS(49) - PPC64_STVS(50) - PPC64_STVS(51) - PPC64_STVS(52) - PPC64_STVS(53) - PPC64_STVS(54) - PPC64_STVS(55) - PPC64_STVS(56) - PPC64_STVS(57) - PPC64_STVS(58) - PPC64_STVS(59) - PPC64_STVS(60) - PPC64_STVS(61) - PPC64_STVS(62) - PPC64_STVS(63) - -#else - -// store FP register -#define PPC64_STF(n) \ - stfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3) - - // save float registers - PPC64_STF(0) - PPC64_STF(1) - PPC64_STF(2) - PPC64_STF(3) - PPC64_STF(4) - PPC64_STF(5) - PPC64_STF(6) - PPC64_STF(7) - PPC64_STF(8) - PPC64_STF(9) - PPC64_STF(10) - PPC64_STF(11) - PPC64_STF(12) - PPC64_STF(13) - PPC64_STF(14) - PPC64_STF(15) - PPC64_STF(16) - PPC64_STF(17) - PPC64_STF(18) - PPC64_STF(19) - PPC64_STF(20) - PPC64_STF(21) - PPC64_STF(22) - PPC64_STF(23) - PPC64_STF(24) - PPC64_STF(25) - PPC64_STF(26) - PPC64_STF(27) - PPC64_STF(28) - PPC64_STF(29) - PPC64_STF(30) - PPC64_STF(31) - - // save vector registers - - // Use 16-bytes below the stack pointer as an - // aligned buffer to save each vector register. - // Note that the stack pointer is always 16-byte aligned. - subi %r4, %r1, 16 - -#define PPC64_STV_UNALIGNED(n) \ - stvx %v##n, 0, %r4 ;\ - ld %r5, 0(%r4) ;\ - std %r5, (PPC64_OFFS_V + n * 16)(%r3) ;\ - ld %r5, 8(%r4) ;\ - std %r5, (PPC64_OFFS_V + n * 16 + 8)(%r3) - - PPC64_STV_UNALIGNED(0) - PPC64_STV_UNALIGNED(1) - PPC64_STV_UNALIGNED(2) - PPC64_STV_UNALIGNED(3) - PPC64_STV_UNALIGNED(4) - PPC64_STV_UNALIGNED(5) - PPC64_STV_UNALIGNED(6) - PPC64_STV_UNALIGNED(7) - PPC64_STV_UNALIGNED(8) - PPC64_STV_UNALIGNED(9) - PPC64_STV_UNALIGNED(10) - PPC64_STV_UNALIGNED(11) - PPC64_STV_UNALIGNED(12) - PPC64_STV_UNALIGNED(13) - PPC64_STV_UNALIGNED(14) - PPC64_STV_UNALIGNED(15) - PPC64_STV_UNALIGNED(16) - PPC64_STV_UNALIGNED(17) - PPC64_STV_UNALIGNED(18) - PPC64_STV_UNALIGNED(19) - PPC64_STV_UNALIGNED(20) - PPC64_STV_UNALIGNED(21) - PPC64_STV_UNALIGNED(22) - PPC64_STV_UNALIGNED(23) - PPC64_STV_UNALIGNED(24) - PPC64_STV_UNALIGNED(25) - PPC64_STV_UNALIGNED(26) - PPC64_STV_UNALIGNED(27) - PPC64_STV_UNALIGNED(28) - PPC64_STV_UNALIGNED(29) - PPC64_STV_UNALIGNED(30) - PPC64_STV_UNALIGNED(31) - -#endif - - li %r3, 0 // return UNW_ESUCCESS - blr - - -#elif defined(__ppc__) - -; -; extern int unw_getcontext(unw_context_t* thread_state) -; -; On entry: -; thread_state pointer is in r3 -; -DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - stw r0, 8(r3) - mflr r0 - stw r0, 0(r3) ; store lr as ssr0 - stw r1, 12(r3) - stw r2, 16(r3) - stw r3, 20(r3) - stw r4, 24(r3) - stw r5, 28(r3) - stw r6, 32(r3) - stw r7, 36(r3) - stw r8, 40(r3) - stw r9, 44(r3) - stw r10, 48(r3) - stw r11, 52(r3) - stw r12, 56(r3) - stw r13, 60(r3) - stw r14, 64(r3) - stw r15, 68(r3) - stw r16, 72(r3) - stw r17, 76(r3) - stw r18, 80(r3) - stw r19, 84(r3) - stw r20, 88(r3) - stw r21, 92(r3) - stw r22, 96(r3) - stw r23,100(r3) - stw r24,104(r3) - stw r25,108(r3) - stw r26,112(r3) - stw r27,116(r3) - stw r28,120(r3) - stw r29,124(r3) - stw r30,128(r3) - stw r31,132(r3) - - ; save VRSave register - mfspr r0,256 - stw r0,156(r3) - ; save CR registers - mfcr r0 - stw r0,136(r3) - ; save CTR register - mfctr r0 - stw r0,148(r3) - - ; save float registers - stfd f0, 160(r3) - stfd f1, 168(r3) - stfd f2, 176(r3) - stfd f3, 184(r3) - stfd f4, 192(r3) - stfd f5, 200(r3) - stfd f6, 208(r3) - stfd f7, 216(r3) - stfd f8, 224(r3) - stfd f9, 232(r3) - stfd f10,240(r3) - stfd f11,248(r3) - stfd f12,256(r3) - stfd f13,264(r3) - stfd f14,272(r3) - stfd f15,280(r3) - stfd f16,288(r3) - stfd f17,296(r3) - stfd f18,304(r3) - stfd f19,312(r3) - stfd f20,320(r3) - stfd f21,328(r3) - stfd f22,336(r3) - stfd f23,344(r3) - stfd f24,352(r3) - stfd f25,360(r3) - stfd f26,368(r3) - stfd f27,376(r3) - stfd f28,384(r3) - stfd f29,392(r3) - stfd f30,400(r3) - stfd f31,408(r3) - - - ; save vector registers - - subi r4,r1,16 - rlwinm r4,r4,0,0,27 ; mask low 4-bits - ; r4 is now a 16-byte aligned pointer into the red zone - -#define SAVE_VECTOR_UNALIGNED(_vec, _offset) \ - stvx _vec,0,r4 @\ - lwz r5, 0(r4) @\ - stw r5, _offset(r3) @\ - lwz r5, 4(r4) @\ - stw r5, _offset+4(r3) @\ - lwz r5, 8(r4) @\ - stw r5, _offset+8(r3) @\ - lwz r5, 12(r4) @\ - stw r5, _offset+12(r3) - - SAVE_VECTOR_UNALIGNED( v0, 424+0x000) - SAVE_VECTOR_UNALIGNED( v1, 424+0x010) - SAVE_VECTOR_UNALIGNED( v2, 424+0x020) - SAVE_VECTOR_UNALIGNED( v3, 424+0x030) - SAVE_VECTOR_UNALIGNED( v4, 424+0x040) - SAVE_VECTOR_UNALIGNED( v5, 424+0x050) - SAVE_VECTOR_UNALIGNED( v6, 424+0x060) - SAVE_VECTOR_UNALIGNED( v7, 424+0x070) - SAVE_VECTOR_UNALIGNED( v8, 424+0x080) - SAVE_VECTOR_UNALIGNED( v9, 424+0x090) - SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0) - SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0) - SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0) - SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0) - SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0) - SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0) - SAVE_VECTOR_UNALIGNED(v16, 424+0x100) - SAVE_VECTOR_UNALIGNED(v17, 424+0x110) - SAVE_VECTOR_UNALIGNED(v18, 424+0x120) - SAVE_VECTOR_UNALIGNED(v19, 424+0x130) - SAVE_VECTOR_UNALIGNED(v20, 424+0x140) - SAVE_VECTOR_UNALIGNED(v21, 424+0x150) - SAVE_VECTOR_UNALIGNED(v22, 424+0x160) - SAVE_VECTOR_UNALIGNED(v23, 424+0x170) - SAVE_VECTOR_UNALIGNED(v24, 424+0x180) - SAVE_VECTOR_UNALIGNED(v25, 424+0x190) - SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0) - SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0) - SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0) - SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0) - SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0) - SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0) - - li r3, 0 ; return UNW_ESUCCESS - blr - - -#elif defined(__arm64__) || defined(__aarch64__) - -// -// extern int unw_getcontext(unw_context_t* thread_state) -// -// On entry: -// thread_state pointer is in x0 -// - .p2align 2 -DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - stp x0, x1, [x0, #0x000] - stp x2, x3, [x0, #0x010] - stp x4, x5, [x0, #0x020] - stp x6, x7, [x0, #0x030] - stp x8, x9, [x0, #0x040] - stp x10,x11, [x0, #0x050] - stp x12,x13, [x0, #0x060] - stp x14,x15, [x0, #0x070] - stp x16,x17, [x0, #0x080] - stp x18,x19, [x0, #0x090] - stp x20,x21, [x0, #0x0A0] - stp x22,x23, [x0, #0x0B0] - stp x24,x25, [x0, #0x0C0] - stp x26,x27, [x0, #0x0D0] - stp x28,x29, [x0, #0x0E0] - str x30, [x0, #0x0F0] - mov x1,sp - str x1, [x0, #0x0F8] - str x30, [x0, #0x100] // store return address as pc - // skip cpsr - stp d0, d1, [x0, #0x110] - stp d2, d3, [x0, #0x120] - stp d4, d5, [x0, #0x130] - stp d6, d7, [x0, #0x140] - stp d8, d9, [x0, #0x150] - stp d10,d11, [x0, #0x160] - stp d12,d13, [x0, #0x170] - stp d14,d15, [x0, #0x180] - stp d16,d17, [x0, #0x190] - stp d18,d19, [x0, #0x1A0] - stp d20,d21, [x0, #0x1B0] - stp d22,d23, [x0, #0x1C0] - stp d24,d25, [x0, #0x1D0] - stp d26,d27, [x0, #0x1E0] - stp d28,d29, [x0, #0x1F0] - str d30, [x0, #0x200] - str d31, [x0, #0x208] - mov x0, #0 // return UNW_ESUCCESS - ret - -#elif defined(__arm__) && !defined(__APPLE__) - -#if !defined(__ARM_ARCH_ISA_ARM) - .thumb -#endif - -@ -@ extern int unw_getcontext(unw_context_t* thread_state) -@ -@ On entry: -@ thread_state pointer is in r0 -@ -@ Per EHABI #4.7 this only saves the core integer registers. -@ EHABI #7.4.5 notes that in general all VRS registers should be restored -@ however this is very hard to do for VFP registers because it is unknown -@ to the library how many registers are implemented by the architecture. -@ Instead, VFP registers are demand saved by logic external to unw_getcontext. -@ - .p2align 2 -DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) -#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1 - stm r0!, {r0-r7} - mov r1, r8 - mov r2, r9 - mov r3, r10 - stm r0!, {r1-r3} - mov r1, r11 - mov r2, sp - mov r3, lr - str r1, [r0, #0] @ r11 - @ r12 does not need storing, it it the intra-procedure-call scratch register - str r2, [r0, #8] @ sp - str r3, [r0, #12] @ lr - str r3, [r0, #16] @ store return address as pc - @ T1 does not have a non-cpsr-clobbering register-zeroing instruction. - @ It is safe to use here though because we are about to return, and cpsr is - @ not expected to be preserved. - movs r0, #0 @ return UNW_ESUCCESS -#else - @ 32bit thumb-2 restrictions for stm: - @ . the sp (r13) cannot be in the list - @ . the pc (r15) cannot be in the list in an STM instruction - stm r0, {r0-r12} - str sp, [r0, #52] - str lr, [r0, #56] - str lr, [r0, #60] @ store return address as pc - mov r0, #0 @ return UNW_ESUCCESS -#endif - JMP(lr) - -@ -@ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values) -@ -@ On entry: -@ values pointer is in r0 -@ - .p2align 2 -#if defined(__ELF__) - .fpu vfpv3-d16 -#endif -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy) - vstmia r0, {d0-d15} - JMP(lr) - -@ -@ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values) -@ -@ On entry: -@ values pointer is in r0 -@ - .p2align 2 -#if defined(__ELF__) - .fpu vfpv3-d16 -#endif -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy) - vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia - JMP(lr) - -@ -@ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values) -@ -@ On entry: -@ values pointer is in r0 -@ - .p2align 2 -#if defined(__ELF__) - .fpu vfpv3 -#endif -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy) - @ VFP and iwMMX instructions are only available when compiling with the flags - @ that enable them. We do not want to do that in the library (because we do not - @ want the compiler to generate instructions that access those) but this is - @ only accessed if the personality routine needs these registers. Use of - @ these registers implies they are, actually, available on the target, so - @ it's ok to execute. - @ So, generate the instructions using the corresponding coprocessor mnemonic. - vstmia r0, {d16-d31} - JMP(lr) - -#if defined(_LIBUNWIND_ARM_WMMX) - -@ -@ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values) -@ -@ On entry: -@ values pointer is in r0 -@ - .p2align 2 -#if defined(__ELF__) - .arch armv5te -#endif -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy) - stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8 - stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8 - stcl p1, cr2, [r0], #8 @ wstrd wR2, [r0], #8 - stcl p1, cr3, [r0], #8 @ wstrd wR3, [r0], #8 - stcl p1, cr4, [r0], #8 @ wstrd wR4, [r0], #8 - stcl p1, cr5, [r0], #8 @ wstrd wR5, [r0], #8 - stcl p1, cr6, [r0], #8 @ wstrd wR6, [r0], #8 - stcl p1, cr7, [r0], #8 @ wstrd wR7, [r0], #8 - stcl p1, cr8, [r0], #8 @ wstrd wR8, [r0], #8 - stcl p1, cr9, [r0], #8 @ wstrd wR9, [r0], #8 - stcl p1, cr10, [r0], #8 @ wstrd wR10, [r0], #8 - stcl p1, cr11, [r0], #8 @ wstrd wR11, [r0], #8 - stcl p1, cr12, [r0], #8 @ wstrd wR12, [r0], #8 - stcl p1, cr13, [r0], #8 @ wstrd wR13, [r0], #8 - stcl p1, cr14, [r0], #8 @ wstrd wR14, [r0], #8 - stcl p1, cr15, [r0], #8 @ wstrd wR15, [r0], #8 - JMP(lr) - -@ -@ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values) -@ -@ On entry: -@ values pointer is in r0 -@ - .p2align 2 -#if defined(__ELF__) - .arch armv5te -#endif -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj) - stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4 - stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4 - stc2 p1, cr10, [r0], #4 @ wstrw wCGR2, [r0], #4 - stc2 p1, cr11, [r0], #4 @ wstrw wCGR3, [r0], #4 - JMP(lr) - -#endif - -#elif defined(__or1k__) - -# -# extern int unw_getcontext(unw_context_t* thread_state) -# -# On entry: -# thread_state pointer is in r3 -# -DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - l.sw 0(r3), r0 - l.sw 4(r3), r1 - l.sw 8(r3), r2 - l.sw 12(r3), r3 - l.sw 16(r3), r4 - l.sw 20(r3), r5 - l.sw 24(r3), r6 - l.sw 28(r3), r7 - l.sw 32(r3), r8 - l.sw 36(r3), r9 - l.sw 40(r3), r10 - l.sw 44(r3), r11 - l.sw 48(r3), r12 - l.sw 52(r3), r13 - l.sw 56(r3), r14 - l.sw 60(r3), r15 - l.sw 64(r3), r16 - l.sw 68(r3), r17 - l.sw 72(r3), r18 - l.sw 76(r3), r19 - l.sw 80(r3), r20 - l.sw 84(r3), r21 - l.sw 88(r3), r22 - l.sw 92(r3), r23 - l.sw 96(r3), r24 - l.sw 100(r3), r25 - l.sw 104(r3), r26 - l.sw 108(r3), r27 - l.sw 112(r3), r28 - l.sw 116(r3), r29 - l.sw 120(r3), r30 - l.sw 124(r3), r31 - # store ra to pc - l.sw 128(r3), r9 - # zero epcr - l.sw 132(r3), r0 - -#elif defined(__riscv) - -# -# extern int unw_getcontext(unw_context_t* thread_state) -# -# On entry: -# thread_state pointer is in a0 -# -DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - // x0 is zero - sd x1, (8 * 1)(a0) - sd x2, (8 * 2)(a0) - sd x3, (8 * 3)(a0) - sd x4, (8 * 4)(a0) - sd x5, (8 * 5)(a0) - sd x6, (8 * 6)(a0) - sd x7, (8 * 7)(a0) - sd x8, (8 * 8)(a0) - sd x9, (8 * 9)(a0) - sd x10, (8 * 10)(a0) - sd x11, (8 * 11)(a0) - sd x12, (8 * 12)(a0) - sd x13, (8 * 13)(a0) - sd x14, (8 * 14)(a0) - sd x15, (8 * 15)(a0) - sd x16, (8 * 16)(a0) - sd x17, (8 * 17)(a0) - sd x18, (8 * 18)(a0) - sd x19, (8 * 19)(a0) - sd x20, (8 * 20)(a0) - sd x21, (8 * 21)(a0) - sd x22, (8 * 22)(a0) - sd x23, (8 * 23)(a0) - sd x24, (8 * 24)(a0) - sd x25, (8 * 25)(a0) - sd x26, (8 * 26)(a0) - sd x27, (8 * 27)(a0) - sd x28, (8 * 28)(a0) - sd x29, (8 * 29)(a0) - sd x30, (8 * 30)(a0) - sd x31, (8 * 31)(a0) - -#ifdef __riscv_float_abi_double - fsd f0, (8 * 32 + 8 * 0)(a0) - fsd f1, (8 * 32 + 8 * 1)(a0) - fsd f2, (8 * 32 + 8 * 2)(a0) - fsd f3, (8 * 32 + 8 * 3)(a0) - fsd f4, (8 * 32 + 8 * 4)(a0) - fsd f5, (8 * 32 + 8 * 5)(a0) - fsd f6, (8 * 32 + 8 * 6)(a0) - fsd f7, (8 * 32 + 8 * 7)(a0) - fsd f8, (8 * 32 + 8 * 8)(a0) - fsd f9, (8 * 32 + 8 * 9)(a0) - fsd f10, (8 * 32 + 8 * 10)(a0) - fsd f11, (8 * 32 + 8 * 11)(a0) - fsd f12, (8 * 32 + 8 * 12)(a0) - fsd f13, (8 * 32 + 8 * 13)(a0) - fsd f14, (8 * 32 + 8 * 14)(a0) - fsd f15, (8 * 32 + 8 * 15)(a0) - fsd f16, (8 * 32 + 8 * 16)(a0) - fsd f17, (8 * 32 + 8 * 17)(a0) - fsd f18, (8 * 32 + 8 * 18)(a0) - fsd f19, (8 * 32 + 8 * 19)(a0) - fsd f20, (8 * 32 + 8 * 20)(a0) - fsd f21, (8 * 32 + 8 * 21)(a0) - fsd f22, (8 * 32 + 8 * 22)(a0) - fsd f23, (8 * 32 + 8 * 23)(a0) - fsd f24, (8 * 32 + 8 * 24)(a0) - fsd f25, (8 * 32 + 8 * 25)(a0) - fsd f26, (8 * 32 + 8 * 26)(a0) - fsd f27, (8 * 32 + 8 * 27)(a0) - fsd f28, (8 * 32 + 8 * 28)(a0) - fsd f29, (8 * 32 + 8 * 29)(a0) - fsd f30, (8 * 32 + 8 * 30)(a0) - fsd f31, (8 * 32 + 8 * 31)(a0) -#endif - - li a0, 0 // return UNW_ESUCCESS - ret // jump to ra - -#elif defined(__sparc__) - -# -# extern int unw_getcontext(unw_context_t* thread_state) -# -# On entry: -# thread_state pointer is in o0 -# -DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - ta 3 - add %o7, 8, %o7 - std %g0, [%o0 + 0] - std %g2, [%o0 + 8] - std %g4, [%o0 + 16] - std %g6, [%o0 + 24] - std %o0, [%o0 + 32] - std %o2, [%o0 + 40] - std %o4, [%o0 + 48] - std %o6, [%o0 + 56] - std %l0, [%o0 + 64] - std %l2, [%o0 + 72] - std %l4, [%o0 + 80] - std %l6, [%o0 + 88] - std %i0, [%o0 + 96] - std %i2, [%o0 + 104] - std %i4, [%o0 + 112] - std %i6, [%o0 + 120] - jmp %o7 - clr %o0 // return UNW_ESUCCESS -#endif -#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ - -NO_EXEC_STACK_DIRECTIVE Property changes on: head/contrib/llvm/projects/libunwind/src/UnwindRegistersSave.S ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S =================================================================== --- head/contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S (nonexistent) @@ -1,1111 +0,0 @@ -//===-------------------- UnwindRegistersRestore.S ------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "assembly.h" - - .text - -#if !defined(__USING_SJLJ_EXCEPTIONS__) - -#if defined(__i386__) -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: -# + + -# +-----------------------+ -# + thread_state pointer + -# +-----------------------+ -# + return address + -# +-----------------------+ <-- 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 - movl %edx, 28(%eax) - movl 0(%eax), %ebx - movl %ebx, 0(%edx) - movl 40(%eax), %ebx - movl %ebx, 4(%edx) - # we now have ret and eax pushed onto where new stack will be - # restore all registers - movl 4(%eax), %ebx - movl 8(%eax), %ecx - movl 12(%eax), %edx - movl 16(%eax), %edi - movl 20(%eax), %esi - movl 24(%eax), %ebp - movl 28(%eax), %esp - # skip ss - # skip eflags - pop %eax # eax was already pushed on new stack - ret # eip was already pushed on new stack - # skip cs - # skip ds - # skip es - # skip fs - # skip gs - -#elif defined(__x86_64__) - -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv) -# -# void libunwind::Registers_x86_64::jumpto() -# -#if defined(_WIN64) -# On entry, thread_state pointer is in rcx; move it into rdi -# to share restore code below. Since this routine restores and -# overwrites all registers, we can use the same registers for -# pointers and temporaries as on unix even though win64 normally -# mustn't clobber some of them. - movq %rcx, %rdi -#else -# On entry, thread_state pointer is in rdi -#endif - - movq 56(%rdi), %rax # rax holds new stack pointer - subq $16, %rax - movq %rax, 56(%rdi) - movq 32(%rdi), %rbx # store new rdi on new stack - movq %rbx, 0(%rax) - movq 128(%rdi), %rbx # store new rip on new stack - movq %rbx, 8(%rax) - # restore all registers - movq 0(%rdi), %rax - movq 8(%rdi), %rbx - movq 16(%rdi), %rcx - movq 24(%rdi), %rdx - # restore rdi later - movq 40(%rdi), %rsi - movq 48(%rdi), %rbp - # restore rsp later - movq 64(%rdi), %r8 - movq 72(%rdi), %r9 - movq 80(%rdi), %r10 - movq 88(%rdi), %r11 - movq 96(%rdi), %r12 - movq 104(%rdi), %r13 - movq 112(%rdi), %r14 - movq 120(%rdi), %r15 - # skip rflags - # skip cs - # skip fs - # skip gs - -#if defined(_WIN64) - movdqu 176(%rdi),%xmm0 - movdqu 192(%rdi),%xmm1 - movdqu 208(%rdi),%xmm2 - movdqu 224(%rdi),%xmm3 - movdqu 240(%rdi),%xmm4 - movdqu 256(%rdi),%xmm5 - movdqu 272(%rdi),%xmm6 - movdqu 288(%rdi),%xmm7 - movdqu 304(%rdi),%xmm8 - movdqu 320(%rdi),%xmm9 - movdqu 336(%rdi),%xmm10 - movdqu 352(%rdi),%xmm11 - movdqu 368(%rdi),%xmm12 - movdqu 384(%rdi),%xmm13 - movdqu 400(%rdi),%xmm14 - movdqu 416(%rdi),%xmm15 -#endif - movq 56(%rdi), %rsp # cut back rsp to new location - pop %rdi # rdi was saved here earlier - ret # rip was saved here - - -#elif defined(__powerpc64__) - -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) -// -// void libunwind::Registers_ppc64::jumpto() -// -// On entry: -// thread_state pointer is in r3 -// - -// load register (GPR) -#define PPC64_LR(n) \ - ld %r##n, (8 * (n + 2))(%r3) - - // restore integral registers - // skip r0 for now - // skip r1 for now - PPC64_LR(2) - // skip r3 for now - // skip r4 for now - // skip r5 for now - PPC64_LR(6) - PPC64_LR(7) - PPC64_LR(8) - PPC64_LR(9) - PPC64_LR(10) - PPC64_LR(11) - PPC64_LR(12) - PPC64_LR(13) - PPC64_LR(14) - PPC64_LR(15) - PPC64_LR(16) - PPC64_LR(17) - PPC64_LR(18) - PPC64_LR(19) - PPC64_LR(20) - PPC64_LR(21) - PPC64_LR(22) - PPC64_LR(23) - PPC64_LR(24) - PPC64_LR(25) - PPC64_LR(26) - PPC64_LR(27) - PPC64_LR(28) - PPC64_LR(29) - PPC64_LR(30) - PPC64_LR(31) - -#ifdef PPC64_HAS_VMX - - // restore VS registers - // (note that this also restores floating point registers and V registers, - // because part of VS is mapped to these registers) - - addi %r4, %r3, PPC64_OFFS_FP - -// load VS register -#define PPC64_LVS(n) \ - lxvd2x %vs##n, 0, %r4 ;\ - addi %r4, %r4, 16 - - // restore the first 32 VS regs (and also all floating point regs) - PPC64_LVS(0) - PPC64_LVS(1) - PPC64_LVS(2) - PPC64_LVS(3) - PPC64_LVS(4) - PPC64_LVS(5) - PPC64_LVS(6) - PPC64_LVS(7) - PPC64_LVS(8) - PPC64_LVS(9) - PPC64_LVS(10) - PPC64_LVS(11) - PPC64_LVS(12) - PPC64_LVS(13) - PPC64_LVS(14) - PPC64_LVS(15) - PPC64_LVS(16) - PPC64_LVS(17) - PPC64_LVS(18) - PPC64_LVS(19) - PPC64_LVS(20) - PPC64_LVS(21) - PPC64_LVS(22) - PPC64_LVS(23) - PPC64_LVS(24) - PPC64_LVS(25) - PPC64_LVS(26) - PPC64_LVS(27) - PPC64_LVS(28) - PPC64_LVS(29) - PPC64_LVS(30) - PPC64_LVS(31) - - // use VRSAVE to conditionally restore the remaining VS regs, - // that are where the V regs are mapped - - ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave - cmpwi %r5, 0 - beq Lnovec - -// conditionally load VS -#define PPC64_CLVS_BOTTOM(n) \ - beq Ldone##n ;\ - addi %r4, %r3, PPC64_OFFS_FP + n * 16 ;\ - lxvd2x %vs##n, 0, %r4 ;\ -Ldone##n: - -#define PPC64_CLVSl(n) \ - andis. %r0, %r5, (1<<(47-n)) ;\ -PPC64_CLVS_BOTTOM(n) - -#define PPC64_CLVSh(n) \ - andi. %r0, %r5, (1<<(63-n)) ;\ -PPC64_CLVS_BOTTOM(n) - - PPC64_CLVSl(32) - PPC64_CLVSl(33) - PPC64_CLVSl(34) - PPC64_CLVSl(35) - PPC64_CLVSl(36) - PPC64_CLVSl(37) - PPC64_CLVSl(38) - PPC64_CLVSl(39) - PPC64_CLVSl(40) - PPC64_CLVSl(41) - PPC64_CLVSl(42) - PPC64_CLVSl(43) - PPC64_CLVSl(44) - PPC64_CLVSl(45) - PPC64_CLVSl(46) - PPC64_CLVSl(47) - PPC64_CLVSh(48) - PPC64_CLVSh(49) - PPC64_CLVSh(50) - PPC64_CLVSh(51) - PPC64_CLVSh(52) - PPC64_CLVSh(53) - PPC64_CLVSh(54) - PPC64_CLVSh(55) - PPC64_CLVSh(56) - PPC64_CLVSh(57) - PPC64_CLVSh(58) - PPC64_CLVSh(59) - PPC64_CLVSh(60) - PPC64_CLVSh(61) - PPC64_CLVSh(62) - PPC64_CLVSh(63) - -#else - -// load FP register -#define PPC64_LF(n) \ - lfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3) - - // restore float registers - PPC64_LF(0) - PPC64_LF(1) - PPC64_LF(2) - PPC64_LF(3) - PPC64_LF(4) - PPC64_LF(5) - PPC64_LF(6) - PPC64_LF(7) - PPC64_LF(8) - PPC64_LF(9) - PPC64_LF(10) - PPC64_LF(11) - PPC64_LF(12) - PPC64_LF(13) - PPC64_LF(14) - PPC64_LF(15) - PPC64_LF(16) - PPC64_LF(17) - PPC64_LF(18) - PPC64_LF(19) - PPC64_LF(20) - PPC64_LF(21) - PPC64_LF(22) - PPC64_LF(23) - PPC64_LF(24) - PPC64_LF(25) - PPC64_LF(26) - PPC64_LF(27) - PPC64_LF(28) - PPC64_LF(29) - PPC64_LF(30) - PPC64_LF(31) - - // restore vector registers if any are in use - ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave - cmpwi %r5, 0 - beq Lnovec - - subi %r4, %r1, 16 - // r4 is now a 16-byte aligned pointer into the red zone - // the _vectorScalarRegisters may not be 16-byte aligned - // so copy via red zone temp buffer - -#define PPC64_CLV_UNALIGNED_BOTTOM(n) \ - beq Ldone##n ;\ - ld %r0, (PPC64_OFFS_V + n * 16)(%r3) ;\ - std %r0, 0(%r4) ;\ - ld %r0, (PPC64_OFFS_V + n * 16 + 8)(%r3) ;\ - std %r0, 8(%r4) ;\ - lvx %v##n, 0, %r4 ;\ -Ldone ## n: - -#define PPC64_CLV_UNALIGNEDl(n) \ - andis. %r0, %r5, (1<<(15-n)) ;\ -PPC64_CLV_UNALIGNED_BOTTOM(n) - -#define PPC64_CLV_UNALIGNEDh(n) \ - andi. %r0, %r5, (1<<(31-n)) ;\ -PPC64_CLV_UNALIGNED_BOTTOM(n) - - PPC64_CLV_UNALIGNEDl(0) - PPC64_CLV_UNALIGNEDl(1) - PPC64_CLV_UNALIGNEDl(2) - PPC64_CLV_UNALIGNEDl(3) - PPC64_CLV_UNALIGNEDl(4) - PPC64_CLV_UNALIGNEDl(5) - PPC64_CLV_UNALIGNEDl(6) - PPC64_CLV_UNALIGNEDl(7) - PPC64_CLV_UNALIGNEDl(8) - PPC64_CLV_UNALIGNEDl(9) - PPC64_CLV_UNALIGNEDl(10) - PPC64_CLV_UNALIGNEDl(11) - PPC64_CLV_UNALIGNEDl(12) - PPC64_CLV_UNALIGNEDl(13) - PPC64_CLV_UNALIGNEDl(14) - PPC64_CLV_UNALIGNEDl(15) - PPC64_CLV_UNALIGNEDh(16) - PPC64_CLV_UNALIGNEDh(17) - PPC64_CLV_UNALIGNEDh(18) - PPC64_CLV_UNALIGNEDh(19) - PPC64_CLV_UNALIGNEDh(20) - PPC64_CLV_UNALIGNEDh(21) - PPC64_CLV_UNALIGNEDh(22) - PPC64_CLV_UNALIGNEDh(23) - PPC64_CLV_UNALIGNEDh(24) - PPC64_CLV_UNALIGNEDh(25) - PPC64_CLV_UNALIGNEDh(26) - PPC64_CLV_UNALIGNEDh(27) - PPC64_CLV_UNALIGNEDh(28) - PPC64_CLV_UNALIGNEDh(29) - PPC64_CLV_UNALIGNEDh(30) - PPC64_CLV_UNALIGNEDh(31) - -#endif - -Lnovec: - ld %r0, PPC64_OFFS_CR(%r3) - mtcr %r0 - ld %r0, PPC64_OFFS_SRR0(%r3) - mtctr %r0 - - PPC64_LR(0) - PPC64_LR(5) - PPC64_LR(4) - PPC64_LR(1) - PPC64_LR(3) - bctr - -#elif defined(__ppc__) - -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) -; -; void libunwind::Registers_ppc::jumpto() -; -; On entry: -; thread_state pointer is in r3 -; - - ; restore integral registerrs - ; skip r0 for now - ; skip r1 for now - lwz r2, 16(r3) - ; skip r3 for now - ; skip r4 for now - ; skip r5 for now - lwz r6, 32(r3) - lwz r7, 36(r3) - lwz r8, 40(r3) - lwz r9, 44(r3) - lwz r10, 48(r3) - lwz r11, 52(r3) - lwz r12, 56(r3) - lwz r13, 60(r3) - lwz r14, 64(r3) - lwz r15, 68(r3) - lwz r16, 72(r3) - lwz r17, 76(r3) - lwz r18, 80(r3) - lwz r19, 84(r3) - lwz r20, 88(r3) - lwz r21, 92(r3) - lwz r22, 96(r3) - lwz r23,100(r3) - lwz r24,104(r3) - lwz r25,108(r3) - lwz r26,112(r3) - lwz r27,116(r3) - lwz r28,120(r3) - lwz r29,124(r3) - lwz r30,128(r3) - lwz r31,132(r3) - - ; restore float registers - lfd f0, 160(r3) - lfd f1, 168(r3) - lfd f2, 176(r3) - lfd f3, 184(r3) - lfd f4, 192(r3) - lfd f5, 200(r3) - lfd f6, 208(r3) - lfd f7, 216(r3) - lfd f8, 224(r3) - lfd f9, 232(r3) - lfd f10,240(r3) - lfd f11,248(r3) - lfd f12,256(r3) - lfd f13,264(r3) - lfd f14,272(r3) - lfd f15,280(r3) - lfd f16,288(r3) - lfd f17,296(r3) - lfd f18,304(r3) - lfd f19,312(r3) - lfd f20,320(r3) - lfd f21,328(r3) - lfd f22,336(r3) - lfd f23,344(r3) - lfd f24,352(r3) - lfd f25,360(r3) - lfd f26,368(r3) - lfd f27,376(r3) - lfd f28,384(r3) - lfd f29,392(r3) - lfd f30,400(r3) - lfd f31,408(r3) - - ; restore vector registers if any are in use - lwz r5,156(r3) ; test VRsave - cmpwi r5,0 - beq Lnovec - - subi r4,r1,16 - rlwinm r4,r4,0,0,27 ; mask low 4-bits - ; r4 is now a 16-byte aligned pointer into the red zone - ; the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer - - -#define LOAD_VECTOR_UNALIGNEDl(_index) \ - andis. r0,r5,(1<<(15-_index)) @\ - beq Ldone ## _index @\ - lwz r0, 424+_index*16(r3) @\ - stw r0, 0(r4) @\ - lwz r0, 424+_index*16+4(r3) @\ - stw r0, 4(r4) @\ - lwz r0, 424+_index*16+8(r3) @\ - stw r0, 8(r4) @\ - lwz r0, 424+_index*16+12(r3)@\ - stw r0, 12(r4) @\ - lvx v ## _index,0,r4 @\ -Ldone ## _index: - -#define LOAD_VECTOR_UNALIGNEDh(_index) \ - andi. r0,r5,(1<<(31-_index)) @\ - beq Ldone ## _index @\ - lwz r0, 424+_index*16(r3) @\ - stw r0, 0(r4) @\ - lwz r0, 424+_index*16+4(r3) @\ - stw r0, 4(r4) @\ - lwz r0, 424+_index*16+8(r3) @\ - stw r0, 8(r4) @\ - lwz r0, 424+_index*16+12(r3)@\ - stw r0, 12(r4) @\ - lvx v ## _index,0,r4 @\ - Ldone ## _index: - - - LOAD_VECTOR_UNALIGNEDl(0) - LOAD_VECTOR_UNALIGNEDl(1) - LOAD_VECTOR_UNALIGNEDl(2) - LOAD_VECTOR_UNALIGNEDl(3) - LOAD_VECTOR_UNALIGNEDl(4) - LOAD_VECTOR_UNALIGNEDl(5) - LOAD_VECTOR_UNALIGNEDl(6) - LOAD_VECTOR_UNALIGNEDl(7) - LOAD_VECTOR_UNALIGNEDl(8) - LOAD_VECTOR_UNALIGNEDl(9) - LOAD_VECTOR_UNALIGNEDl(10) - LOAD_VECTOR_UNALIGNEDl(11) - LOAD_VECTOR_UNALIGNEDl(12) - LOAD_VECTOR_UNALIGNEDl(13) - LOAD_VECTOR_UNALIGNEDl(14) - LOAD_VECTOR_UNALIGNEDl(15) - LOAD_VECTOR_UNALIGNEDh(16) - LOAD_VECTOR_UNALIGNEDh(17) - LOAD_VECTOR_UNALIGNEDh(18) - LOAD_VECTOR_UNALIGNEDh(19) - LOAD_VECTOR_UNALIGNEDh(20) - LOAD_VECTOR_UNALIGNEDh(21) - LOAD_VECTOR_UNALIGNEDh(22) - LOAD_VECTOR_UNALIGNEDh(23) - LOAD_VECTOR_UNALIGNEDh(24) - LOAD_VECTOR_UNALIGNEDh(25) - LOAD_VECTOR_UNALIGNEDh(26) - LOAD_VECTOR_UNALIGNEDh(27) - LOAD_VECTOR_UNALIGNEDh(28) - LOAD_VECTOR_UNALIGNEDh(29) - LOAD_VECTOR_UNALIGNEDh(30) - LOAD_VECTOR_UNALIGNEDh(31) - -Lnovec: - lwz r0, 136(r3) ; __cr - mtocrf 255,r0 - lwz r0, 148(r3) ; __ctr - mtctr r0 - lwz r0, 0(r3) ; __ssr0 - mtctr r0 - lwz r0, 8(r3) ; do r0 now - lwz r5,28(r3) ; do r5 now - lwz r4,24(r3) ; do r4 now - lwz r1,12(r3) ; do sp now - lwz r3,20(r3) ; do r3 last - bctr - -#elif defined(__arm64__) || defined(__aarch64__) - -// -// void libunwind::Registers_arm64::jumpto() -// -// On entry: -// thread_state pointer is in x0 -// - .p2align 2 -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) - // skip restore of x0,x1 for now - ldp x2, x3, [x0, #0x010] - ldp x4, x5, [x0, #0x020] - ldp x6, x7, [x0, #0x030] - ldp x8, x9, [x0, #0x040] - ldp x10,x11, [x0, #0x050] - ldp x12,x13, [x0, #0x060] - ldp x14,x15, [x0, #0x070] - ldp x16,x17, [x0, #0x080] - ldp x18,x19, [x0, #0x090] - ldp x20,x21, [x0, #0x0A0] - ldp x22,x23, [x0, #0x0B0] - ldp x24,x25, [x0, #0x0C0] - ldp x26,x27, [x0, #0x0D0] - ldp x28,x29, [x0, #0x0E0] - ldr x30, [x0, #0x100] // restore pc into lr - ldr x1, [x0, #0x0F8] - mov sp,x1 // restore sp - - ldp d0, d1, [x0, #0x110] - ldp d2, d3, [x0, #0x120] - ldp d4, d5, [x0, #0x130] - ldp d6, d7, [x0, #0x140] - ldp d8, d9, [x0, #0x150] - ldp d10,d11, [x0, #0x160] - ldp d12,d13, [x0, #0x170] - ldp d14,d15, [x0, #0x180] - ldp d16,d17, [x0, #0x190] - ldp d18,d19, [x0, #0x1A0] - ldp d20,d21, [x0, #0x1B0] - ldp d22,d23, [x0, #0x1C0] - ldp d24,d25, [x0, #0x1D0] - ldp d26,d27, [x0, #0x1E0] - ldp d28,d29, [x0, #0x1F0] - ldr d30, [x0, #0x200] - ldr d31, [x0, #0x208] - - ldp x0, x1, [x0, #0x000] // restore x0,x1 - ret x30 // jump to pc - -#elif defined(__arm__) && !defined(__APPLE__) - -#if !defined(__ARM_ARCH_ISA_ARM) - .thumb -#endif - -@ -@ void libunwind::Registers_arm::restoreCoreAndJumpTo() -@ -@ On entry: -@ thread_state pointer is in r0 -@ - .p2align 2 -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv) -#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1 - @ r8-r11: ldm into r1-r4, then mov to r8-r11 - adds r0, #0x20 - ldm r0!, {r1-r4} - subs r0, #0x30 - mov r8, r1 - mov r9, r2 - mov r10, r3 - mov r11, r4 - @ r12 does not need loading, it it the intra-procedure-call scratch register - ldr r2, [r0, #0x34] - ldr r3, [r0, #0x3c] - mov sp, r2 - mov lr, r3 @ restore pc into lr - ldm r0, {r0-r7} -#else - @ Use lr as base so that r0 can be restored. - mov lr, r0 - @ 32bit thumb-2 restrictions for ldm: - @ . the sp (r13) cannot be in the list - @ . the pc (r15) and lr (r14) cannot both be in the list in an LDM instruction - ldm lr, {r0-r12} - ldr sp, [lr, #52] - ldr lr, [lr, #60] @ restore pc into lr -#endif - JMP(lr) - -@ -@ static void libunwind::Registers_arm::restoreVFPWithFLDMD(unw_fpreg_t* values) -@ -@ On entry: -@ values pointer is in r0 -@ - .p2align 2 -#if defined(__ELF__) - .fpu vfpv3-d16 -#endif -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPy) - @ VFP and iwMMX instructions are only available when compiling with the flags - @ that enable them. We do not want to do that in the library (because we do not - @ want the compiler to generate instructions that access those) but this is - @ only accessed if the personality routine needs these registers. Use of - @ these registers implies they are, actually, available on the target, so - @ it's ok to execute. - @ So, generate the instruction using the corresponding coprocessor mnemonic. - vldmia r0, {d0-d15} - JMP(lr) - -@ -@ static void libunwind::Registers_arm::restoreVFPWithFLDMX(unw_fpreg_t* values) -@ -@ On entry: -@ values pointer is in r0 -@ - .p2align 2 -#if defined(__ELF__) - .fpu vfpv3-d16 -#endif -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPy) - vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia - JMP(lr) - -@ -@ static void libunwind::Registers_arm::restoreVFPv3(unw_fpreg_t* values) -@ -@ On entry: -@ values pointer is in r0 -@ - .p2align 2 -#if defined(__ELF__) - .fpu vfpv3 -#endif -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy) - vldmia r0, {d16-d31} - JMP(lr) - -#if defined(__ARM_WMMX) - -@ -@ static void libunwind::Registers_arm::restoreiWMMX(unw_fpreg_t* values) -@ -@ On entry: -@ values pointer is in r0 -@ - .p2align 2 -#if defined(__ELF__) - .arch armv5te -#endif -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy) - ldcl p1, cr0, [r0], #8 @ wldrd wR0, [r0], #8 - ldcl p1, cr1, [r0], #8 @ wldrd wR1, [r0], #8 - ldcl p1, cr2, [r0], #8 @ wldrd wR2, [r0], #8 - ldcl p1, cr3, [r0], #8 @ wldrd wR3, [r0], #8 - ldcl p1, cr4, [r0], #8 @ wldrd wR4, [r0], #8 - ldcl p1, cr5, [r0], #8 @ wldrd wR5, [r0], #8 - ldcl p1, cr6, [r0], #8 @ wldrd wR6, [r0], #8 - ldcl p1, cr7, [r0], #8 @ wldrd wR7, [r0], #8 - ldcl p1, cr8, [r0], #8 @ wldrd wR8, [r0], #8 - ldcl p1, cr9, [r0], #8 @ wldrd wR9, [r0], #8 - ldcl p1, cr10, [r0], #8 @ wldrd wR10, [r0], #8 - ldcl p1, cr11, [r0], #8 @ wldrd wR11, [r0], #8 - ldcl p1, cr12, [r0], #8 @ wldrd wR12, [r0], #8 - ldcl p1, cr13, [r0], #8 @ wldrd wR13, [r0], #8 - ldcl p1, cr14, [r0], #8 @ wldrd wR14, [r0], #8 - ldcl p1, cr15, [r0], #8 @ wldrd wR15, [r0], #8 - JMP(lr) - -@ -@ static void libunwind::Registers_arm::restoreiWMMXControl(unw_uint32_t* values) -@ -@ On entry: -@ values pointer is in r0 -@ - .p2align 2 -#if defined(__ELF__) - .arch armv5te -#endif -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj) - ldc2 p1, cr8, [r0], #4 @ wldrw wCGR0, [r0], #4 - ldc2 p1, cr9, [r0], #4 @ wldrw wCGR1, [r0], #4 - ldc2 p1, cr10, [r0], #4 @ wldrw wCGR2, [r0], #4 - ldc2 p1, cr11, [r0], #4 @ wldrw wCGR3, [r0], #4 - JMP(lr) - -#endif - -#elif defined(__or1k__) - -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) -# -# void libunwind::Registers_or1k::jumpto() -# -# On entry: -# thread_state pointer is in r3 -# - - # restore integral registers - l.lwz r0, 0(r3) - l.lwz r1, 4(r3) - l.lwz r2, 8(r3) - # skip r3 for now - l.lwz r4, 16(r3) - l.lwz r5, 20(r3) - l.lwz r6, 24(r3) - l.lwz r7, 28(r3) - l.lwz r8, 32(r3) - # skip r9 - l.lwz r10, 40(r3) - l.lwz r11, 44(r3) - l.lwz r12, 48(r3) - l.lwz r13, 52(r3) - l.lwz r14, 56(r3) - l.lwz r15, 60(r3) - l.lwz r16, 64(r3) - l.lwz r17, 68(r3) - l.lwz r18, 72(r3) - l.lwz r19, 76(r3) - l.lwz r20, 80(r3) - l.lwz r21, 84(r3) - l.lwz r22, 88(r3) - l.lwz r23, 92(r3) - l.lwz r24, 96(r3) - l.lwz r25,100(r3) - l.lwz r26,104(r3) - l.lwz r27,108(r3) - l.lwz r28,112(r3) - l.lwz r29,116(r3) - l.lwz r30,120(r3) - l.lwz r31,124(r3) - - # at last, restore r3 - l.lwz r3, 12(r3) - - # load new pc into ra - l.lwz r9, 128(r3) - # jump to pc - l.jr r9 - l.nop - -#elif defined(__riscv) - -// -// void libunwind::Registers_riscv::jumpto() -// -// On entry: -// thread_state pointer is in a0 -// - .p2align 2 -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) -#ifdef __riscv_float_abi_double - fld f0, (8 * 32 + 8 * 0)(a0) - fld f1, (8 * 32 + 8 * 1)(a0) - fld f2, (8 * 32 + 8 * 2)(a0) - fld f3, (8 * 32 + 8 * 3)(a0) - fld f4, (8 * 32 + 8 * 4)(a0) - fld f5, (8 * 32 + 8 * 5)(a0) - fld f6, (8 * 32 + 8 * 6)(a0) - fld f7, (8 * 32 + 8 * 7)(a0) - fld f8, (8 * 32 + 8 * 8)(a0) - fld f9, (8 * 32 + 8 * 9)(a0) - fld f10, (8 * 32 + 8 * 10)(a0) - fld f11, (8 * 32 + 8 * 11)(a0) - fld f12, (8 * 32 + 8 * 12)(a0) - fld f13, (8 * 32 + 8 * 13)(a0) - fld f14, (8 * 32 + 8 * 14)(a0) - fld f15, (8 * 32 + 8 * 15)(a0) - fld f16, (8 * 32 + 8 * 16)(a0) - fld f17, (8 * 32 + 8 * 17)(a0) - fld f18, (8 * 32 + 8 * 18)(a0) - fld f19, (8 * 32 + 8 * 19)(a0) - fld f20, (8 * 32 + 8 * 20)(a0) - fld f21, (8 * 32 + 8 * 21)(a0) - fld f22, (8 * 32 + 8 * 22)(a0) - fld f23, (8 * 32 + 8 * 23)(a0) - fld f24, (8 * 32 + 8 * 24)(a0) - fld f25, (8 * 32 + 8 * 25)(a0) - fld f26, (8 * 32 + 8 * 26)(a0) - fld f27, (8 * 32 + 8 * 27)(a0) - fld f28, (8 * 32 + 8 * 28)(a0) - fld f29, (8 * 32 + 8 * 29)(a0) - fld f30, (8 * 32 + 8 * 30)(a0) - fld f31, (8 * 32 + 8 * 31)(a0) -#endif - - // x0 is zero - ld x1, (8 * 1)(a0) - ld x2, (8 * 2)(a0) - ld x3, (8 * 3)(a0) - ld x4, (8 * 4)(a0) - ld x5, (8 * 5)(a0) - ld x6, (8 * 6)(a0) - ld x7, (8 * 7)(a0) - ld x8, (8 * 8)(a0) - ld x9, (8 * 9)(a0) - // skip a0 for now - ld x11, (8 * 11)(a0) - ld x12, (8 * 12)(a0) - ld x13, (8 * 13)(a0) - ld x14, (8 * 14)(a0) - ld x15, (8 * 15)(a0) - ld x16, (8 * 16)(a0) - ld x17, (8 * 17)(a0) - ld x18, (8 * 18)(a0) - ld x19, (8 * 19)(a0) - ld x20, (8 * 20)(a0) - ld x21, (8 * 21)(a0) - ld x22, (8 * 22)(a0) - ld x23, (8 * 23)(a0) - ld x24, (8 * 24)(a0) - ld x25, (8 * 25)(a0) - ld x26, (8 * 26)(a0) - ld x27, (8 * 27)(a0) - ld x28, (8 * 28)(a0) - ld x29, (8 * 29)(a0) - ld x30, (8 * 30)(a0) - ld x31, (8 * 31)(a0) - ld x10, (8 * 10)(a0) // restore a0 - - ret // jump to ra - -#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 - -// -// void libunwind::Registers_mips_o32::jumpto() -// -// On entry: -// thread state pointer is in a0 ($4) -// -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) - .set push - .set noat - .set noreorder - .set nomacro -#ifdef __mips_hard_float -#if __mips_fpr != 64 - ldc1 $f0, (4 * 36 + 8 * 0)($4) - ldc1 $f2, (4 * 36 + 8 * 2)($4) - ldc1 $f4, (4 * 36 + 8 * 4)($4) - ldc1 $f6, (4 * 36 + 8 * 6)($4) - ldc1 $f8, (4 * 36 + 8 * 8)($4) - ldc1 $f10, (4 * 36 + 8 * 10)($4) - ldc1 $f12, (4 * 36 + 8 * 12)($4) - ldc1 $f14, (4 * 36 + 8 * 14)($4) - ldc1 $f16, (4 * 36 + 8 * 16)($4) - ldc1 $f18, (4 * 36 + 8 * 18)($4) - ldc1 $f20, (4 * 36 + 8 * 20)($4) - ldc1 $f22, (4 * 36 + 8 * 22)($4) - ldc1 $f24, (4 * 36 + 8 * 24)($4) - ldc1 $f26, (4 * 36 + 8 * 26)($4) - ldc1 $f28, (4 * 36 + 8 * 28)($4) - ldc1 $f30, (4 * 36 + 8 * 30)($4) -#else - ldc1 $f0, (4 * 36 + 8 * 0)($4) - ldc1 $f1, (4 * 36 + 8 * 1)($4) - ldc1 $f2, (4 * 36 + 8 * 2)($4) - ldc1 $f3, (4 * 36 + 8 * 3)($4) - ldc1 $f4, (4 * 36 + 8 * 4)($4) - ldc1 $f5, (4 * 36 + 8 * 5)($4) - ldc1 $f6, (4 * 36 + 8 * 6)($4) - ldc1 $f7, (4 * 36 + 8 * 7)($4) - ldc1 $f8, (4 * 36 + 8 * 8)($4) - ldc1 $f9, (4 * 36 + 8 * 9)($4) - ldc1 $f10, (4 * 36 + 8 * 10)($4) - ldc1 $f11, (4 * 36 + 8 * 11)($4) - ldc1 $f12, (4 * 36 + 8 * 12)($4) - ldc1 $f13, (4 * 36 + 8 * 13)($4) - ldc1 $f14, (4 * 36 + 8 * 14)($4) - ldc1 $f15, (4 * 36 + 8 * 15)($4) - ldc1 $f16, (4 * 36 + 8 * 16)($4) - ldc1 $f17, (4 * 36 + 8 * 17)($4) - ldc1 $f18, (4 * 36 + 8 * 18)($4) - ldc1 $f19, (4 * 36 + 8 * 19)($4) - ldc1 $f20, (4 * 36 + 8 * 20)($4) - ldc1 $f21, (4 * 36 + 8 * 21)($4) - ldc1 $f22, (4 * 36 + 8 * 22)($4) - ldc1 $f23, (4 * 36 + 8 * 23)($4) - ldc1 $f24, (4 * 36 + 8 * 24)($4) - ldc1 $f25, (4 * 36 + 8 * 25)($4) - ldc1 $f26, (4 * 36 + 8 * 26)($4) - ldc1 $f27, (4 * 36 + 8 * 27)($4) - ldc1 $f28, (4 * 36 + 8 * 28)($4) - ldc1 $f29, (4 * 36 + 8 * 29)($4) - ldc1 $f30, (4 * 36 + 8 * 30)($4) - ldc1 $f31, (4 * 36 + 8 * 31)($4) -#endif -#endif - // restore hi and lo - lw $8, (4 * 33)($4) - mthi $8 - lw $8, (4 * 34)($4) - mtlo $8 - // r0 is zero - lw $1, (4 * 1)($4) - lw $2, (4 * 2)($4) - lw $3, (4 * 3)($4) - // skip a0 for now - lw $5, (4 * 5)($4) - lw $6, (4 * 6)($4) - lw $7, (4 * 7)($4) - lw $8, (4 * 8)($4) - lw $9, (4 * 9)($4) - lw $10, (4 * 10)($4) - lw $11, (4 * 11)($4) - lw $12, (4 * 12)($4) - lw $13, (4 * 13)($4) - lw $14, (4 * 14)($4) - lw $15, (4 * 15)($4) - lw $16, (4 * 16)($4) - lw $17, (4 * 17)($4) - lw $18, (4 * 18)($4) - lw $19, (4 * 19)($4) - lw $20, (4 * 20)($4) - lw $21, (4 * 21)($4) - lw $22, (4 * 22)($4) - lw $23, (4 * 23)($4) - lw $24, (4 * 24)($4) - lw $25, (4 * 25)($4) - lw $26, (4 * 26)($4) - lw $27, (4 * 27)($4) - lw $28, (4 * 28)($4) - lw $29, (4 * 29)($4) - lw $30, (4 * 30)($4) - // load new pc into ra - lw $31, (4 * 32)($4) - // jump to ra, load a0 in the delay slot - jr $31 - lw $4, (4 * 4)($4) - .set pop - -#elif defined(__mips64) - -// -// void libunwind::Registers_mips_newabi::jumpto() -// -// On entry: -// thread state pointer is in a0 ($4) -// -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) - .set push - .set noat - .set noreorder - .set nomacro -#ifdef __mips_hard_float - ldc1 $f0, (8 * 35)($4) - ldc1 $f1, (8 * 36)($4) - ldc1 $f2, (8 * 37)($4) - ldc1 $f3, (8 * 38)($4) - ldc1 $f4, (8 * 39)($4) - ldc1 $f5, (8 * 40)($4) - ldc1 $f6, (8 * 41)($4) - ldc1 $f7, (8 * 42)($4) - ldc1 $f8, (8 * 43)($4) - ldc1 $f9, (8 * 44)($4) - ldc1 $f10, (8 * 45)($4) - ldc1 $f11, (8 * 46)($4) - ldc1 $f12, (8 * 47)($4) - ldc1 $f13, (8 * 48)($4) - ldc1 $f14, (8 * 49)($4) - ldc1 $f15, (8 * 50)($4) - ldc1 $f16, (8 * 51)($4) - ldc1 $f17, (8 * 52)($4) - ldc1 $f18, (8 * 53)($4) - ldc1 $f19, (8 * 54)($4) - ldc1 $f20, (8 * 55)($4) - ldc1 $f21, (8 * 56)($4) - ldc1 $f22, (8 * 57)($4) - ldc1 $f23, (8 * 58)($4) - ldc1 $f24, (8 * 59)($4) - ldc1 $f25, (8 * 60)($4) - ldc1 $f26, (8 * 61)($4) - ldc1 $f27, (8 * 62)($4) - ldc1 $f28, (8 * 63)($4) - ldc1 $f29, (8 * 64)($4) - ldc1 $f30, (8 * 65)($4) - ldc1 $f31, (8 * 66)($4) -#endif - // restore hi and lo - ld $8, (8 * 33)($4) - mthi $8 - ld $8, (8 * 34)($4) - mtlo $8 - // r0 is zero - ld $1, (8 * 1)($4) - ld $2, (8 * 2)($4) - ld $3, (8 * 3)($4) - // skip a0 for now - ld $5, (8 * 5)($4) - ld $6, (8 * 6)($4) - ld $7, (8 * 7)($4) - ld $8, (8 * 8)($4) - ld $9, (8 * 9)($4) - ld $10, (8 * 10)($4) - ld $11, (8 * 11)($4) - ld $12, (8 * 12)($4) - ld $13, (8 * 13)($4) - ld $14, (8 * 14)($4) - ld $15, (8 * 15)($4) - ld $16, (8 * 16)($4) - ld $17, (8 * 17)($4) - ld $18, (8 * 18)($4) - ld $19, (8 * 19)($4) - ld $20, (8 * 20)($4) - ld $21, (8 * 21)($4) - ld $22, (8 * 22)($4) - ld $23, (8 * 23)($4) - ld $24, (8 * 24)($4) - ld $25, (8 * 25)($4) - ld $26, (8 * 26)($4) - ld $27, (8 * 27)($4) - ld $28, (8 * 28)($4) - ld $29, (8 * 29)($4) - ld $30, (8 * 30)($4) - // load new pc into ra - ld $31, (8 * 32)($4) - // jump to ra, load a0 in the delay slot - jr $31 - ld $4, (8 * 4)($4) - .set pop - -#elif defined(__sparc__) - -// -// void libunwind::Registers_sparc_o32::jumpto() -// -// On entry: -// thread_state pointer is in o0 -// -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv) - ta 3 - ldd [%o0 + 64], %l0 - ldd [%o0 + 72], %l2 - ldd [%o0 + 80], %l4 - ldd [%o0 + 88], %l6 - ldd [%o0 + 96], %i0 - ldd [%o0 + 104], %i2 - ldd [%o0 + 112], %i4 - ldd [%o0 + 120], %i6 - ld [%o0 + 60], %o7 - jmp %o7 - nop - -#endif - -#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ - -NO_EXEC_STACK_DIRECTIVE - Property changes on: head/contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/UnwindCursor.hpp =================================================================== --- head/contrib/llvm/projects/libunwind/src/UnwindCursor.hpp (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/UnwindCursor.hpp (nonexistent) @@ -1,1981 +0,0 @@ -//===------------------------- UnwindCursor.hpp ---------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// C++ interface to lower levels of libunwind -//===----------------------------------------------------------------------===// - -#ifndef __UNWINDCURSOR_HPP__ -#define __UNWINDCURSOR_HPP__ - -#include -#include -#include -#include -#include - -#ifdef _WIN32 - #include - #include -#endif -#ifdef __APPLE__ - #include -#endif - -#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) -// Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and -// earlier) SDKs. -// MinGW-w64 has always provided this struct. - #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \ - !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000 -struct _DISPATCHER_CONTEXT { - ULONG64 ControlPc; - ULONG64 ImageBase; - PRUNTIME_FUNCTION FunctionEntry; - ULONG64 EstablisherFrame; - ULONG64 TargetIp; - PCONTEXT ContextRecord; - PEXCEPTION_ROUTINE LanguageHandler; - PVOID HandlerData; - PUNWIND_HISTORY_TABLE HistoryTable; - ULONG ScopeIndex; - ULONG Fill0; -}; - #endif - -struct UNWIND_INFO { - uint8_t Version : 3; - uint8_t Flags : 5; - uint8_t SizeOfProlog; - uint8_t CountOfCodes; - uint8_t FrameRegister : 4; - uint8_t FrameOffset : 4; - uint16_t UnwindCodes[2]; -}; - -extern "C" _Unwind_Reason_Code __libunwind_seh_personality( - int, _Unwind_Action, uint64_t, _Unwind_Exception *, - struct _Unwind_Context *); - -#endif - -#include "config.h" - -#include "AddressSpace.hpp" -#include "CompactUnwinder.hpp" -#include "config.h" -#include "DwarfInstructions.hpp" -#include "EHHeaderParser.hpp" -#include "libunwind.h" -#include "Registers.hpp" -#include "RWMutex.hpp" -#include "Unwind-EHABI.h" - -namespace libunwind { - -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) -/// Cache of recently found FDEs. -template -class _LIBUNWIND_HIDDEN DwarfFDECache { - typedef typename A::pint_t pint_t; -public: - static pint_t findFDE(pint_t mh, pint_t pc); - static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde); - static void removeAllIn(pint_t mh); - static void iterateCacheEntries(void (*func)(unw_word_t ip_start, - unw_word_t ip_end, - unw_word_t fde, unw_word_t mh)); - -private: - - struct entry { - pint_t mh; - pint_t ip_start; - pint_t ip_end; - pint_t fde; - }; - - // These fields are all static to avoid needing an initializer. - // There is only one instance of this class per process. - static RWMutex _lock; -#ifdef __APPLE__ - static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide); - static bool _registeredForDyldUnloads; -#endif - // Can't use std::vector<> here because this code is below libc++. - static entry *_buffer; - static entry *_bufferUsed; - static entry *_bufferEnd; - static entry _initialBuffer[64]; -}; - -template -typename DwarfFDECache::entry * -DwarfFDECache::_buffer = _initialBuffer; - -template -typename DwarfFDECache::entry * -DwarfFDECache::_bufferUsed = _initialBuffer; - -template -typename DwarfFDECache::entry * -DwarfFDECache::_bufferEnd = &_initialBuffer[64]; - -template -typename DwarfFDECache::entry DwarfFDECache::_initialBuffer[64]; - -template -RWMutex DwarfFDECache::_lock; - -#ifdef __APPLE__ -template -bool DwarfFDECache::_registeredForDyldUnloads = false; -#endif - -template -typename A::pint_t DwarfFDECache::findFDE(pint_t mh, pint_t pc) { - pint_t result = 0; - _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); - for (entry *p = _buffer; p < _bufferUsed; ++p) { - if ((mh == p->mh) || (mh == 0)) { - if ((p->ip_start <= pc) && (pc < p->ip_end)) { - result = p->fde; - break; - } - } - } - _LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared()); - return result; -} - -template -void DwarfFDECache::add(pint_t mh, pint_t ip_start, pint_t ip_end, - pint_t fde) { -#if !defined(_LIBUNWIND_NO_HEAP) - _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); - if (_bufferUsed >= _bufferEnd) { - size_t oldSize = (size_t)(_bufferEnd - _buffer); - size_t newSize = oldSize * 4; - // Can't use operator new (we are below it). - entry *newBuffer = (entry *)malloc(newSize * sizeof(entry)); - memcpy(newBuffer, _buffer, oldSize * sizeof(entry)); - if (_buffer != _initialBuffer) - free(_buffer); - _buffer = newBuffer; - _bufferUsed = &newBuffer[oldSize]; - _bufferEnd = &newBuffer[newSize]; - } - _bufferUsed->mh = mh; - _bufferUsed->ip_start = ip_start; - _bufferUsed->ip_end = ip_end; - _bufferUsed->fde = fde; - ++_bufferUsed; -#ifdef __APPLE__ - if (!_registeredForDyldUnloads) { - _dyld_register_func_for_remove_image(&dyldUnloadHook); - _registeredForDyldUnloads = true; - } -#endif - _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); -#endif -} - -template -void DwarfFDECache::removeAllIn(pint_t mh) { - _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); - entry *d = _buffer; - for (const entry *s = _buffer; s < _bufferUsed; ++s) { - if (s->mh != mh) { - if (d != s) - *d = *s; - ++d; - } - } - _bufferUsed = d; - _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); -} - -#ifdef __APPLE__ -template -void DwarfFDECache::dyldUnloadHook(const struct mach_header *mh, intptr_t ) { - removeAllIn((pint_t) mh); -} -#endif - -template -void DwarfFDECache::iterateCacheEntries(void (*func)( - unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { - _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); - for (entry *p = _buffer; p < _bufferUsed; ++p) { - (*func)(p->ip_start, p->ip_end, p->fde, p->mh); - } - _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); -} -#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - - -#define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field)) - -#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) -template class UnwindSectionHeader { -public: - UnwindSectionHeader(A &addressSpace, typename A::pint_t addr) - : _addressSpace(addressSpace), _addr(addr) {} - - uint32_t version() const { - return _addressSpace.get32(_addr + - offsetof(unwind_info_section_header, version)); - } - uint32_t commonEncodingsArraySectionOffset() const { - return _addressSpace.get32(_addr + - offsetof(unwind_info_section_header, - commonEncodingsArraySectionOffset)); - } - uint32_t commonEncodingsArrayCount() const { - return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, - commonEncodingsArrayCount)); - } - uint32_t personalityArraySectionOffset() const { - return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, - personalityArraySectionOffset)); - } - uint32_t personalityArrayCount() const { - return _addressSpace.get32( - _addr + offsetof(unwind_info_section_header, personalityArrayCount)); - } - uint32_t indexSectionOffset() const { - return _addressSpace.get32( - _addr + offsetof(unwind_info_section_header, indexSectionOffset)); - } - uint32_t indexCount() const { - return _addressSpace.get32( - _addr + offsetof(unwind_info_section_header, indexCount)); - } - -private: - A &_addressSpace; - typename A::pint_t _addr; -}; - -template class UnwindSectionIndexArray { -public: - UnwindSectionIndexArray(A &addressSpace, typename A::pint_t addr) - : _addressSpace(addressSpace), _addr(addr) {} - - uint32_t functionOffset(uint32_t index) const { - return _addressSpace.get32( - _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, - functionOffset)); - } - uint32_t secondLevelPagesSectionOffset(uint32_t index) const { - return _addressSpace.get32( - _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, - secondLevelPagesSectionOffset)); - } - uint32_t lsdaIndexArraySectionOffset(uint32_t index) const { - return _addressSpace.get32( - _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, - lsdaIndexArraySectionOffset)); - } - -private: - A &_addressSpace; - typename A::pint_t _addr; -}; - -template class UnwindSectionRegularPageHeader { -public: - UnwindSectionRegularPageHeader(A &addressSpace, typename A::pint_t addr) - : _addressSpace(addressSpace), _addr(addr) {} - - uint32_t kind() const { - return _addressSpace.get32( - _addr + offsetof(unwind_info_regular_second_level_page_header, kind)); - } - uint16_t entryPageOffset() const { - return _addressSpace.get16( - _addr + offsetof(unwind_info_regular_second_level_page_header, - entryPageOffset)); - } - uint16_t entryCount() const { - return _addressSpace.get16( - _addr + - offsetof(unwind_info_regular_second_level_page_header, entryCount)); - } - -private: - A &_addressSpace; - typename A::pint_t _addr; -}; - -template class UnwindSectionRegularArray { -public: - UnwindSectionRegularArray(A &addressSpace, typename A::pint_t addr) - : _addressSpace(addressSpace), _addr(addr) {} - - uint32_t functionOffset(uint32_t index) const { - return _addressSpace.get32( - _addr + arrayoffsetof(unwind_info_regular_second_level_entry, index, - functionOffset)); - } - uint32_t encoding(uint32_t index) const { - return _addressSpace.get32( - _addr + - arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding)); - } - -private: - A &_addressSpace; - typename A::pint_t _addr; -}; - -template class UnwindSectionCompressedPageHeader { -public: - UnwindSectionCompressedPageHeader(A &addressSpace, typename A::pint_t addr) - : _addressSpace(addressSpace), _addr(addr) {} - - uint32_t kind() const { - return _addressSpace.get32( - _addr + - offsetof(unwind_info_compressed_second_level_page_header, kind)); - } - uint16_t entryPageOffset() const { - return _addressSpace.get16( - _addr + offsetof(unwind_info_compressed_second_level_page_header, - entryPageOffset)); - } - uint16_t entryCount() const { - return _addressSpace.get16( - _addr + - offsetof(unwind_info_compressed_second_level_page_header, entryCount)); - } - uint16_t encodingsPageOffset() const { - return _addressSpace.get16( - _addr + offsetof(unwind_info_compressed_second_level_page_header, - encodingsPageOffset)); - } - uint16_t encodingsCount() const { - return _addressSpace.get16( - _addr + offsetof(unwind_info_compressed_second_level_page_header, - encodingsCount)); - } - -private: - A &_addressSpace; - typename A::pint_t _addr; -}; - -template class UnwindSectionCompressedArray { -public: - UnwindSectionCompressedArray(A &addressSpace, typename A::pint_t addr) - : _addressSpace(addressSpace), _addr(addr) {} - - uint32_t functionOffset(uint32_t index) const { - return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET( - _addressSpace.get32(_addr + index * sizeof(uint32_t))); - } - uint16_t encodingIndex(uint32_t index) const { - return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX( - _addressSpace.get32(_addr + index * sizeof(uint32_t))); - } - -private: - A &_addressSpace; - typename A::pint_t _addr; -}; - -template class UnwindSectionLsdaArray { -public: - UnwindSectionLsdaArray(A &addressSpace, typename A::pint_t addr) - : _addressSpace(addressSpace), _addr(addr) {} - - uint32_t functionOffset(uint32_t index) const { - return _addressSpace.get32( - _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, - index, functionOffset)); - } - uint32_t lsdaOffset(uint32_t index) const { - return _addressSpace.get32( - _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, - index, lsdaOffset)); - } - -private: - A &_addressSpace; - typename A::pint_t _addr; -}; -#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) - -class _LIBUNWIND_HIDDEN AbstractUnwindCursor { -public: - // NOTE: provide a class specific placement deallocation function (S5.3.4 p20) - // This avoids an unnecessary dependency to libc++abi. - void operator delete(void *, size_t) {} - - virtual ~AbstractUnwindCursor() {} - virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); } - virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); } - virtual void setReg(int, unw_word_t) { - _LIBUNWIND_ABORT("setReg not implemented"); - } - virtual bool validFloatReg(int) { - _LIBUNWIND_ABORT("validFloatReg not implemented"); - } - virtual unw_fpreg_t getFloatReg(int) { - _LIBUNWIND_ABORT("getFloatReg not implemented"); - } - virtual void setFloatReg(int, unw_fpreg_t) { - _LIBUNWIND_ABORT("setFloatReg not implemented"); - } - virtual int step() { _LIBUNWIND_ABORT("step not implemented"); } - virtual void getInfo(unw_proc_info_t *) { - _LIBUNWIND_ABORT("getInfo not implemented"); - } - virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); } - virtual bool isSignalFrame() { - _LIBUNWIND_ABORT("isSignalFrame not implemented"); - } - virtual bool getFunctionName(char *, size_t, unw_word_t *) { - _LIBUNWIND_ABORT("getFunctionName not implemented"); - } - virtual void setInfoBasedOnIPRegister(bool = false) { - _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented"); - } - virtual const char *getRegisterName(int) { - _LIBUNWIND_ABORT("getRegisterName not implemented"); - } -#ifdef __arm__ - virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); } -#endif -}; - -#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) - -/// \c UnwindCursor contains all state (including all register values) during -/// an unwind. This is normally stack-allocated inside a unw_cursor_t. -template -class UnwindCursor : public AbstractUnwindCursor { - typedef typename A::pint_t pint_t; -public: - UnwindCursor(unw_context_t *context, A &as); - UnwindCursor(CONTEXT *context, A &as); - UnwindCursor(A &as, void *threadArg); - virtual ~UnwindCursor() {} - virtual bool validReg(int); - virtual unw_word_t getReg(int); - virtual void setReg(int, unw_word_t); - virtual bool validFloatReg(int); - virtual unw_fpreg_t getFloatReg(int); - virtual void setFloatReg(int, unw_fpreg_t); - virtual int step(); - virtual void getInfo(unw_proc_info_t *); - virtual void jumpto(); - virtual bool isSignalFrame(); - virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); - virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); - virtual const char *getRegisterName(int num); -#ifdef __arm__ - virtual void saveVFPAsX(); -#endif - - DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; } - void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; } - -private: - - pint_t getLastPC() const { return _dispContext.ControlPc; } - void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; } - RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) { - _dispContext.FunctionEntry = RtlLookupFunctionEntry(pc, - &_dispContext.ImageBase, - _dispContext.HistoryTable); - *base = _dispContext.ImageBase; - return _dispContext.FunctionEntry; - } - bool getInfoFromSEH(pint_t pc); - int stepWithSEHData() { - _dispContext.LanguageHandler = RtlVirtualUnwind(UNW_FLAG_UHANDLER, - _dispContext.ImageBase, - _dispContext.ControlPc, - _dispContext.FunctionEntry, - _dispContext.ContextRecord, - &_dispContext.HandlerData, - &_dispContext.EstablisherFrame, - NULL); - // Update some fields of the unwind info now, since we have them. - _info.lsda = reinterpret_cast(_dispContext.HandlerData); - if (_dispContext.LanguageHandler) { - _info.handler = reinterpret_cast(__libunwind_seh_personality); - } else - _info.handler = 0; - return UNW_STEP_SUCCESS; - } - - A &_addressSpace; - unw_proc_info_t _info; - DISPATCHER_CONTEXT _dispContext; - CONTEXT _msContext; - UNWIND_HISTORY_TABLE _histTable; - bool _unwindInfoMissing; -}; - - -template -UnwindCursor::UnwindCursor(unw_context_t *context, A &as) - : _addressSpace(as), _unwindInfoMissing(false) { - static_assert((check_fit, unw_cursor_t>::does_fit), - "UnwindCursor<> does not fit in unw_cursor_t"); - memset(&_info, 0, sizeof(_info)); - memset(&_histTable, 0, sizeof(_histTable)); - _dispContext.ContextRecord = &_msContext; - _dispContext.HistoryTable = &_histTable; - // Initialize MS context from ours. - R r(context); - _msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT; -#if defined(_LIBUNWIND_TARGET_X86_64) - _msContext.Rax = r.getRegister(UNW_X86_64_RAX); - _msContext.Rcx = r.getRegister(UNW_X86_64_RCX); - _msContext.Rdx = r.getRegister(UNW_X86_64_RDX); - _msContext.Rbx = r.getRegister(UNW_X86_64_RBX); - _msContext.Rsp = r.getRegister(UNW_X86_64_RSP); - _msContext.Rbp = r.getRegister(UNW_X86_64_RBP); - _msContext.Rsi = r.getRegister(UNW_X86_64_RSI); - _msContext.Rdi = r.getRegister(UNW_X86_64_RDI); - _msContext.R8 = r.getRegister(UNW_X86_64_R8); - _msContext.R9 = r.getRegister(UNW_X86_64_R9); - _msContext.R10 = r.getRegister(UNW_X86_64_R10); - _msContext.R11 = r.getRegister(UNW_X86_64_R11); - _msContext.R12 = r.getRegister(UNW_X86_64_R12); - _msContext.R13 = r.getRegister(UNW_X86_64_R13); - _msContext.R14 = r.getRegister(UNW_X86_64_R14); - _msContext.R15 = r.getRegister(UNW_X86_64_R15); - _msContext.Rip = r.getRegister(UNW_REG_IP); - union { - v128 v; - M128A m; - } t; - t.v = r.getVectorRegister(UNW_X86_64_XMM0); - _msContext.Xmm0 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM1); - _msContext.Xmm1 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM2); - _msContext.Xmm2 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM3); - _msContext.Xmm3 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM4); - _msContext.Xmm4 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM5); - _msContext.Xmm5 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM6); - _msContext.Xmm6 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM7); - _msContext.Xmm7 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM8); - _msContext.Xmm8 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM9); - _msContext.Xmm9 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM10); - _msContext.Xmm10 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM11); - _msContext.Xmm11 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM12); - _msContext.Xmm12 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM13); - _msContext.Xmm13 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM14); - _msContext.Xmm14 = t.m; - t.v = r.getVectorRegister(UNW_X86_64_XMM15); - _msContext.Xmm15 = t.m; -#elif defined(_LIBUNWIND_TARGET_ARM) - _msContext.R0 = r.getRegister(UNW_ARM_R0); - _msContext.R1 = r.getRegister(UNW_ARM_R1); - _msContext.R2 = r.getRegister(UNW_ARM_R2); - _msContext.R3 = r.getRegister(UNW_ARM_R3); - _msContext.R4 = r.getRegister(UNW_ARM_R4); - _msContext.R5 = r.getRegister(UNW_ARM_R5); - _msContext.R6 = r.getRegister(UNW_ARM_R6); - _msContext.R7 = r.getRegister(UNW_ARM_R7); - _msContext.R8 = r.getRegister(UNW_ARM_R8); - _msContext.R9 = r.getRegister(UNW_ARM_R9); - _msContext.R10 = r.getRegister(UNW_ARM_R10); - _msContext.R11 = r.getRegister(UNW_ARM_R11); - _msContext.R12 = r.getRegister(UNW_ARM_R12); - _msContext.Sp = r.getRegister(UNW_ARM_SP); - _msContext.Lr = r.getRegister(UNW_ARM_LR); - _msContext.Pc = r.getRegister(UNW_ARM_IP); - for (int i = UNW_ARM_D0; i <= UNW_ARM_D31; ++i) { - union { - uint64_t w; - double d; - } d; - d.d = r.getFloatRegister(i); - _msContext.D[i - UNW_ARM_D0] = d.w; - } -#elif defined(_LIBUNWIND_TARGET_AARCH64) - for (int i = UNW_ARM64_X0; i <= UNW_ARM64_X30; ++i) - _msContext.X[i - UNW_ARM64_X0] = r.getRegister(i); - _msContext.Sp = r.getRegister(UNW_REG_SP); - _msContext.Pc = r.getRegister(UNW_REG_IP); - for (int i = UNW_ARM64_D0; i <= UNW_ARM64_D31; ++i) - _msContext.V[i - UNW_ARM64_D0].D[0] = r.getFloatRegister(i); -#endif -} - -template -UnwindCursor::UnwindCursor(CONTEXT *context, A &as) - : _addressSpace(as), _unwindInfoMissing(false) { - static_assert((check_fit, unw_cursor_t>::does_fit), - "UnwindCursor<> does not fit in unw_cursor_t"); - memset(&_info, 0, sizeof(_info)); - memset(&_histTable, 0, sizeof(_histTable)); - _dispContext.ContextRecord = &_msContext; - _dispContext.HistoryTable = &_histTable; - _msContext = *context; -} - - -template -bool UnwindCursor::validReg(int regNum) { - if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true; -#if defined(_LIBUNWIND_TARGET_X86_64) - if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true; -#elif defined(_LIBUNWIND_TARGET_ARM) - if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) return true; -#elif defined(_LIBUNWIND_TARGET_AARCH64) - if (regNum >= UNW_ARM64_X0 && regNum <= UNW_ARM64_X30) return true; -#endif - return false; -} - -template -unw_word_t UnwindCursor::getReg(int regNum) { - switch (regNum) { -#if defined(_LIBUNWIND_TARGET_X86_64) - case UNW_REG_IP: return _msContext.Rip; - case UNW_X86_64_RAX: return _msContext.Rax; - case UNW_X86_64_RDX: return _msContext.Rdx; - case UNW_X86_64_RCX: return _msContext.Rcx; - case UNW_X86_64_RBX: return _msContext.Rbx; - case UNW_REG_SP: - case UNW_X86_64_RSP: return _msContext.Rsp; - case UNW_X86_64_RBP: return _msContext.Rbp; - case UNW_X86_64_RSI: return _msContext.Rsi; - case UNW_X86_64_RDI: return _msContext.Rdi; - case UNW_X86_64_R8: return _msContext.R8; - case UNW_X86_64_R9: return _msContext.R9; - case UNW_X86_64_R10: return _msContext.R10; - case UNW_X86_64_R11: return _msContext.R11; - case UNW_X86_64_R12: return _msContext.R12; - case UNW_X86_64_R13: return _msContext.R13; - case UNW_X86_64_R14: return _msContext.R14; - case UNW_X86_64_R15: return _msContext.R15; -#elif defined(_LIBUNWIND_TARGET_ARM) - case UNW_ARM_R0: return _msContext.R0; - case UNW_ARM_R1: return _msContext.R1; - case UNW_ARM_R2: return _msContext.R2; - case UNW_ARM_R3: return _msContext.R3; - case UNW_ARM_R4: return _msContext.R4; - case UNW_ARM_R5: return _msContext.R5; - case UNW_ARM_R6: return _msContext.R6; - case UNW_ARM_R7: return _msContext.R7; - case UNW_ARM_R8: return _msContext.R8; - case UNW_ARM_R9: return _msContext.R9; - case UNW_ARM_R10: return _msContext.R10; - case UNW_ARM_R11: return _msContext.R11; - case UNW_ARM_R12: return _msContext.R12; - case UNW_REG_SP: - case UNW_ARM_SP: return _msContext.Sp; - case UNW_ARM_LR: return _msContext.Lr; - case UNW_REG_IP: - case UNW_ARM_IP: return _msContext.Pc; -#elif defined(_LIBUNWIND_TARGET_AARCH64) - case UNW_REG_SP: return _msContext.Sp; - case UNW_REG_IP: return _msContext.Pc; - default: return _msContext.X[regNum - UNW_ARM64_X0]; -#endif - } - _LIBUNWIND_ABORT("unsupported register"); -} - -template -void UnwindCursor::setReg(int regNum, unw_word_t value) { - switch (regNum) { -#if defined(_LIBUNWIND_TARGET_X86_64) - case UNW_REG_IP: _msContext.Rip = value; break; - case UNW_X86_64_RAX: _msContext.Rax = value; break; - case UNW_X86_64_RDX: _msContext.Rdx = value; break; - case UNW_X86_64_RCX: _msContext.Rcx = value; break; - case UNW_X86_64_RBX: _msContext.Rbx = value; break; - case UNW_REG_SP: - case UNW_X86_64_RSP: _msContext.Rsp = value; break; - case UNW_X86_64_RBP: _msContext.Rbp = value; break; - case UNW_X86_64_RSI: _msContext.Rsi = value; break; - case UNW_X86_64_RDI: _msContext.Rdi = value; break; - case UNW_X86_64_R8: _msContext.R8 = value; break; - case UNW_X86_64_R9: _msContext.R9 = value; break; - case UNW_X86_64_R10: _msContext.R10 = value; break; - case UNW_X86_64_R11: _msContext.R11 = value; break; - case UNW_X86_64_R12: _msContext.R12 = value; break; - case UNW_X86_64_R13: _msContext.R13 = value; break; - case UNW_X86_64_R14: _msContext.R14 = value; break; - case UNW_X86_64_R15: _msContext.R15 = value; break; -#elif defined(_LIBUNWIND_TARGET_ARM) - case UNW_ARM_R0: _msContext.R0 = value; break; - case UNW_ARM_R1: _msContext.R1 = value; break; - case UNW_ARM_R2: _msContext.R2 = value; break; - case UNW_ARM_R3: _msContext.R3 = value; break; - case UNW_ARM_R4: _msContext.R4 = value; break; - case UNW_ARM_R5: _msContext.R5 = value; break; - case UNW_ARM_R6: _msContext.R6 = value; break; - case UNW_ARM_R7: _msContext.R7 = value; break; - case UNW_ARM_R8: _msContext.R8 = value; break; - case UNW_ARM_R9: _msContext.R9 = value; break; - case UNW_ARM_R10: _msContext.R10 = value; break; - case UNW_ARM_R11: _msContext.R11 = value; break; - case UNW_ARM_R12: _msContext.R12 = value; break; - case UNW_REG_SP: - case UNW_ARM_SP: _msContext.Sp = value; break; - case UNW_ARM_LR: _msContext.Lr = value; break; - case UNW_REG_IP: - case UNW_ARM_IP: _msContext.Pc = value; break; -#elif defined(_LIBUNWIND_TARGET_AARCH64) - case UNW_REG_SP: _msContext.Sp = value; break; - case UNW_REG_IP: _msContext.Pc = value; break; - case UNW_ARM64_X0: - case UNW_ARM64_X1: - case UNW_ARM64_X2: - case UNW_ARM64_X3: - case UNW_ARM64_X4: - case UNW_ARM64_X5: - case UNW_ARM64_X6: - case UNW_ARM64_X7: - case UNW_ARM64_X8: - case UNW_ARM64_X9: - case UNW_ARM64_X10: - case UNW_ARM64_X11: - case UNW_ARM64_X12: - case UNW_ARM64_X13: - case UNW_ARM64_X14: - case UNW_ARM64_X15: - case UNW_ARM64_X16: - case UNW_ARM64_X17: - case UNW_ARM64_X18: - case UNW_ARM64_X19: - case UNW_ARM64_X20: - case UNW_ARM64_X21: - case UNW_ARM64_X22: - case UNW_ARM64_X23: - case UNW_ARM64_X24: - case UNW_ARM64_X25: - case UNW_ARM64_X26: - case UNW_ARM64_X27: - case UNW_ARM64_X28: - case UNW_ARM64_FP: - case UNW_ARM64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break; -#endif - default: - _LIBUNWIND_ABORT("unsupported register"); - } -} - -template -bool UnwindCursor::validFloatReg(int regNum) { -#if defined(_LIBUNWIND_TARGET_ARM) - if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true; - if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true; -#elif defined(_LIBUNWIND_TARGET_AARCH64) - if (regNum >= UNW_ARM64_D0 && regNum <= UNW_ARM64_D31) return true; -#endif - return false; -} - -template -unw_fpreg_t UnwindCursor::getFloatReg(int regNum) { -#if defined(_LIBUNWIND_TARGET_ARM) - if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) { - union { - uint32_t w; - float f; - } d; - d.w = _msContext.S[regNum - UNW_ARM_S0]; - return d.f; - } - if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) { - union { - uint64_t w; - double d; - } d; - d.w = _msContext.D[regNum - UNW_ARM_D0]; - return d.d; - } - _LIBUNWIND_ABORT("unsupported float register"); -#elif defined(_LIBUNWIND_TARGET_AARCH64) - return _msContext.V[regNum - UNW_ARM64_D0].D[0]; -#else - _LIBUNWIND_ABORT("float registers unimplemented"); -#endif -} - -template -void UnwindCursor::setFloatReg(int regNum, unw_fpreg_t value) { -#if defined(_LIBUNWIND_TARGET_ARM) - if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) { - union { - uint32_t w; - float f; - } d; - d.f = value; - _msContext.S[regNum - UNW_ARM_S0] = d.w; - } - if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) { - union { - uint64_t w; - double d; - } d; - d.d = value; - _msContext.D[regNum - UNW_ARM_D0] = d.w; - } - _LIBUNWIND_ABORT("unsupported float register"); -#elif defined(_LIBUNWIND_TARGET_AARCH64) - _msContext.V[regNum - UNW_ARM64_D0].D[0] = value; -#else - _LIBUNWIND_ABORT("float registers unimplemented"); -#endif -} - -template void UnwindCursor::jumpto() { - RtlRestoreContext(&_msContext, nullptr); -} - -#ifdef __arm__ -template void UnwindCursor::saveVFPAsX() {} -#endif - -template -const char *UnwindCursor::getRegisterName(int regNum) { - return R::getRegisterName(regNum); -} - -template bool UnwindCursor::isSignalFrame() { - return false; -} - -#else // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32) - -/// UnwindCursor contains all state (including all register values) during -/// an unwind. This is normally stack allocated inside a unw_cursor_t. -template -class UnwindCursor : public AbstractUnwindCursor{ - typedef typename A::pint_t pint_t; -public: - UnwindCursor(unw_context_t *context, A &as); - UnwindCursor(A &as, void *threadArg); - virtual ~UnwindCursor() {} - virtual bool validReg(int); - virtual unw_word_t getReg(int); - virtual void setReg(int, unw_word_t); - virtual bool validFloatReg(int); - virtual unw_fpreg_t getFloatReg(int); - virtual void setFloatReg(int, unw_fpreg_t); - virtual int step(); - virtual void getInfo(unw_proc_info_t *); - virtual void jumpto(); - virtual bool isSignalFrame(); - virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); - virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); - virtual const char *getRegisterName(int num); -#ifdef __arm__ - virtual void saveVFPAsX(); -#endif - -private: - -#if defined(_LIBUNWIND_ARM_EHABI) - bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections §s); - - int stepWithEHABI() { - size_t len = 0; - size_t off = 0; - // FIXME: Calling decode_eht_entry() here is violating the libunwind - // abstraction layer. - const uint32_t *ehtp = - decode_eht_entry(reinterpret_cast(_info.unwind_info), - &off, &len); - if (_Unwind_VRS_Interpret((_Unwind_Context *)this, ehtp, off, len) != - _URC_CONTINUE_UNWIND) - return UNW_STEP_END; - return UNW_STEP_SUCCESS; - } -#endif - -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections §s, - uint32_t fdeSectionOffsetHint=0); - int stepWithDwarfFDE() { - return DwarfInstructions::stepWithDwarf(_addressSpace, - (pint_t)this->getReg(UNW_REG_IP), - (pint_t)_info.unwind_info, - _registers); - } -#endif - -#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) - bool getInfoFromCompactEncodingSection(pint_t pc, - const UnwindInfoSections §s); - int stepWithCompactEncoding() { - #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - if ( compactSaysUseDwarf() ) - return stepWithDwarfFDE(); - #endif - R dummy; - return stepWithCompactEncoding(dummy); - } - -#if defined(_LIBUNWIND_TARGET_X86_64) - int stepWithCompactEncoding(Registers_x86_64 &) { - return CompactUnwinder_x86_64::stepWithCompactEncoding( - _info.format, _info.start_ip, _addressSpace, _registers); - } -#endif - -#if defined(_LIBUNWIND_TARGET_I386) - int stepWithCompactEncoding(Registers_x86 &) { - return CompactUnwinder_x86::stepWithCompactEncoding( - _info.format, (uint32_t)_info.start_ip, _addressSpace, _registers); - } -#endif - -#if defined(_LIBUNWIND_TARGET_PPC) - int stepWithCompactEncoding(Registers_ppc &) { - return UNW_EINVAL; - } -#endif - -#if defined(_LIBUNWIND_TARGET_PPC64) - int stepWithCompactEncoding(Registers_ppc64 &) { - return UNW_EINVAL; - } -#endif - - -#if defined(_LIBUNWIND_TARGET_AARCH64) - int stepWithCompactEncoding(Registers_arm64 &) { - return CompactUnwinder_arm64::stepWithCompactEncoding( - _info.format, _info.start_ip, _addressSpace, _registers); - } -#endif - -#if defined(_LIBUNWIND_TARGET_MIPS_O32) - int stepWithCompactEncoding(Registers_mips_o32 &) { - return UNW_EINVAL; - } -#endif - -#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) - int stepWithCompactEncoding(Registers_mips_newabi &) { - return UNW_EINVAL; - } -#endif - -#if defined(_LIBUNWIND_TARGET_SPARC) - int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; } -#endif - - bool compactSaysUseDwarf(uint32_t *offset=NULL) const { - R dummy; - return compactSaysUseDwarf(dummy, offset); - } - -#if defined(_LIBUNWIND_TARGET_X86_64) - bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const { - if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) { - if (offset) - *offset = (_info.format & UNWIND_X86_64_DWARF_SECTION_OFFSET); - return true; - } - return false; - } -#endif - -#if defined(_LIBUNWIND_TARGET_I386) - bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const { - if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) { - if (offset) - *offset = (_info.format & UNWIND_X86_DWARF_SECTION_OFFSET); - return true; - } - return false; - } -#endif - -#if defined(_LIBUNWIND_TARGET_PPC) - bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const { - return true; - } -#endif - -#if defined(_LIBUNWIND_TARGET_PPC64) - bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const { - return true; - } -#endif - -#if defined(_LIBUNWIND_TARGET_AARCH64) - bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const { - if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) { - if (offset) - *offset = (_info.format & UNWIND_ARM64_DWARF_SECTION_OFFSET); - return true; - } - return false; - } -#endif - -#if defined(_LIBUNWIND_TARGET_MIPS_O32) - bool compactSaysUseDwarf(Registers_mips_o32 &, uint32_t *) const { - return true; - } -#endif - -#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) - bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const { - return true; - } -#endif - -#if defined(_LIBUNWIND_TARGET_SPARC) - bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; } -#endif - -#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) - -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - compact_unwind_encoding_t dwarfEncoding() const { - R dummy; - return dwarfEncoding(dummy); - } - -#if defined(_LIBUNWIND_TARGET_X86_64) - compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const { - return UNWIND_X86_64_MODE_DWARF; - } -#endif - -#if defined(_LIBUNWIND_TARGET_I386) - compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const { - return UNWIND_X86_MODE_DWARF; - } -#endif - -#if defined(_LIBUNWIND_TARGET_PPC) - compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const { - return 0; - } -#endif - -#if defined(_LIBUNWIND_TARGET_PPC64) - compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const { - return 0; - } -#endif - -#if defined(_LIBUNWIND_TARGET_AARCH64) - compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const { - return UNWIND_ARM64_MODE_DWARF; - } -#endif - -#if defined(_LIBUNWIND_TARGET_ARM) - compact_unwind_encoding_t dwarfEncoding(Registers_arm &) const { - return 0; - } -#endif - -#if defined (_LIBUNWIND_TARGET_OR1K) - compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const { - return 0; - } -#endif - -#if defined (_LIBUNWIND_TARGET_RISCV) - compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const { - return 0; - } -#endif - -#if defined (_LIBUNWIND_TARGET_MIPS_O32) - compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const { - return 0; - } -#endif - -#if defined (_LIBUNWIND_TARGET_MIPS_NEWABI) - compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const { - return 0; - } -#endif - -#if defined(_LIBUNWIND_TARGET_SPARC) - compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; } -#endif - -#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - -#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) - // For runtime environments using SEH unwind data without Windows runtime - // support. - pint_t getLastPC() const { /* FIXME: Implement */ return 0; } - void setLastPC(pint_t pc) { /* FIXME: Implement */ } - RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) { - /* FIXME: Implement */ - *base = 0; - return nullptr; - } - bool getInfoFromSEH(pint_t pc); - int stepWithSEHData() { /* FIXME: Implement */ return 0; } -#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) - - - A &_addressSpace; - R _registers; - unw_proc_info_t _info; - bool _unwindInfoMissing; - bool _isSignalFrame; -}; - - -template -UnwindCursor::UnwindCursor(unw_context_t *context, A &as) - : _addressSpace(as), _registers(context), _unwindInfoMissing(false), - _isSignalFrame(false) { - static_assert((check_fit, unw_cursor_t>::does_fit), - "UnwindCursor<> does not fit in unw_cursor_t"); - memset(&_info, 0, sizeof(_info)); -} - -template -UnwindCursor::UnwindCursor(A &as, void *) - : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) { - memset(&_info, 0, sizeof(_info)); - // FIXME - // fill in _registers from thread arg -} - - -template -bool UnwindCursor::validReg(int regNum) { - return _registers.validRegister(regNum); -} - -template -unw_word_t UnwindCursor::getReg(int regNum) { - return _registers.getRegister(regNum); -} - -template -void UnwindCursor::setReg(int regNum, unw_word_t value) { - _registers.setRegister(regNum, (typename A::pint_t)value); -} - -template -bool UnwindCursor::validFloatReg(int regNum) { - return _registers.validFloatRegister(regNum); -} - -template -unw_fpreg_t UnwindCursor::getFloatReg(int regNum) { - return _registers.getFloatRegister(regNum); -} - -template -void UnwindCursor::setFloatReg(int regNum, unw_fpreg_t value) { - _registers.setFloatRegister(regNum, value); -} - -template void UnwindCursor::jumpto() { - _registers.jumpto(); -} - -#ifdef __arm__ -template void UnwindCursor::saveVFPAsX() { - _registers.saveVFPAsX(); -} -#endif - -template -const char *UnwindCursor::getRegisterName(int regNum) { - return _registers.getRegisterName(regNum); -} - -template bool UnwindCursor::isSignalFrame() { - return _isSignalFrame; -} - -#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) - -#if defined(_LIBUNWIND_ARM_EHABI) -struct EHABIIndexEntry { - uint32_t functionOffset; - uint32_t data; -}; - -template -struct EHABISectionIterator { - typedef EHABISectionIterator _Self; - - typedef std::random_access_iterator_tag iterator_category; - typedef typename A::pint_t value_type; - typedef typename A::pint_t* pointer; - typedef typename A::pint_t& reference; - typedef size_t size_type; - typedef size_t difference_type; - - static _Self begin(A& addressSpace, const UnwindInfoSections& sects) { - return _Self(addressSpace, sects, 0); - } - static _Self end(A& addressSpace, const UnwindInfoSections& sects) { - return _Self(addressSpace, sects, - sects.arm_section_length / sizeof(EHABIIndexEntry)); - } - - EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i) - : _i(i), _addressSpace(&addressSpace), _sects(§s) {} - - _Self& operator++() { ++_i; return *this; } - _Self& operator+=(size_t a) { _i += a; return *this; } - _Self& operator--() { assert(_i > 0); --_i; return *this; } - _Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; } - - _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; } - _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; } - - size_t operator-(const _Self& other) { return _i - other._i; } - - bool operator==(const _Self& other) const { - assert(_addressSpace == other._addressSpace); - assert(_sects == other._sects); - return _i == other._i; - } - - typename A::pint_t operator*() const { return functionAddress(); } - - typename A::pint_t functionAddress() const { - typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof( - EHABIIndexEntry, _i, functionOffset); - return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr)); - } - - typename A::pint_t dataAddress() { - typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof( - EHABIIndexEntry, _i, data); - return indexAddr; - } - - private: - size_t _i; - A* _addressSpace; - const UnwindInfoSections* _sects; -}; - -template -bool UnwindCursor::getInfoFromEHABISection( - pint_t pc, - const UnwindInfoSections §s) { - EHABISectionIterator begin = - EHABISectionIterator::begin(_addressSpace, sects); - EHABISectionIterator end = - EHABISectionIterator::end(_addressSpace, sects); - if (begin == end) - return false; - - EHABISectionIterator itNextPC = std::upper_bound(begin, end, pc); - if (itNextPC == begin) - return false; - EHABISectionIterator itThisPC = itNextPC - 1; - - pint_t thisPC = itThisPC.functionAddress(); - // If an exception is thrown from a function, corresponding to the last entry - // in the table, we don't really know the function extent and have to choose a - // value for nextPC. Choosing max() will allow the range check during trace to - // succeed. - pint_t nextPC = (itNextPC == end) ? std::numeric_limits::max() - : itNextPC.functionAddress(); - pint_t indexDataAddr = itThisPC.dataAddress(); - - if (indexDataAddr == 0) - return false; - - uint32_t indexData = _addressSpace.get32(indexDataAddr); - if (indexData == UNW_EXIDX_CANTUNWIND) - return false; - - // If the high bit is set, the exception handling table entry is inline inside - // the index table entry on the second word (aka |indexDataAddr|). Otherwise, - // the table points at an offset in the exception handling table (section 5 EHABI). - pint_t exceptionTableAddr; - uint32_t exceptionTableData; - bool isSingleWordEHT; - if (indexData & 0x80000000) { - exceptionTableAddr = indexDataAddr; - // TODO(ajwong): Should this data be 0? - exceptionTableData = indexData; - isSingleWordEHT = true; - } else { - exceptionTableAddr = indexDataAddr + signExtendPrel31(indexData); - exceptionTableData = _addressSpace.get32(exceptionTableAddr); - isSingleWordEHT = false; - } - - // Now we know the 3 things: - // exceptionTableAddr -- exception handler table entry. - // exceptionTableData -- the data inside the first word of the eht entry. - // isSingleWordEHT -- whether the entry is in the index. - unw_word_t personalityRoutine = 0xbadf00d; - bool scope32 = false; - uintptr_t lsda; - - // If the high bit in the exception handling table entry is set, the entry is - // in compact form (section 6.3 EHABI). - if (exceptionTableData & 0x80000000) { - // Grab the index of the personality routine from the compact form. - uint32_t choice = (exceptionTableData & 0x0f000000) >> 24; - uint32_t extraWords = 0; - switch (choice) { - case 0: - personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0; - extraWords = 0; - scope32 = false; - lsda = isSingleWordEHT ? 0 : (exceptionTableAddr + 4); - break; - case 1: - personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr1; - extraWords = (exceptionTableData & 0x00ff0000) >> 16; - scope32 = false; - lsda = exceptionTableAddr + (extraWords + 1) * 4; - break; - case 2: - personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr2; - extraWords = (exceptionTableData & 0x00ff0000) >> 16; - scope32 = true; - lsda = exceptionTableAddr + (extraWords + 1) * 4; - break; - default: - _LIBUNWIND_ABORT("unknown personality routine"); - return false; - } - - if (isSingleWordEHT) { - if (extraWords != 0) { - _LIBUNWIND_ABORT("index inlined table detected but pr function " - "requires extra words"); - return false; - } - } - } else { - pint_t personalityAddr = - exceptionTableAddr + signExtendPrel31(exceptionTableData); - personalityRoutine = personalityAddr; - - // ARM EHABI # 6.2, # 9.2 - // - // +---- ehtp - // v - // +--------------------------------------+ - // | +--------+--------+--------+-------+ | - // | |0| prel31 to personalityRoutine | | - // | +--------+--------+--------+-------+ | - // | | N | unwind opcodes | | <-- UnwindData - // | +--------+--------+--------+-------+ | - // | | Word 2 unwind opcodes | | - // | +--------+--------+--------+-------+ | - // | ... | - // | +--------+--------+--------+-------+ | - // | | Word N unwind opcodes | | - // | +--------+--------+--------+-------+ | - // | | LSDA | | <-- lsda - // | | ... | | - // | +--------+--------+--------+-------+ | - // +--------------------------------------+ - - uint32_t *UnwindData = reinterpret_cast(exceptionTableAddr) + 1; - uint32_t FirstDataWord = *UnwindData; - size_t N = ((FirstDataWord >> 24) & 0xff); - size_t NDataWords = N + 1; - lsda = reinterpret_cast(UnwindData + NDataWords); - } - - _info.start_ip = thisPC; - _info.end_ip = nextPC; - _info.handler = personalityRoutine; - _info.unwind_info = exceptionTableAddr; - _info.lsda = lsda; - // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0. - _info.flags = isSingleWordEHT ? 1 : 0 | scope32 ? 0x2 : 0; // Use enum? - - return true; -} -#endif - -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) -template -bool UnwindCursor::getInfoFromDwarfSection(pint_t pc, - const UnwindInfoSections §s, - uint32_t fdeSectionOffsetHint) { - typename CFI_Parser::FDE_Info fdeInfo; - typename CFI_Parser::CIE_Info cieInfo; - bool foundFDE = false; - bool foundInCache = false; - // If compact encoding table gave offset into dwarf section, go directly there - if (fdeSectionOffsetHint != 0) { - foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, - (uint32_t)sects.dwarf_section_length, - sects.dwarf_section + fdeSectionOffsetHint, - &fdeInfo, &cieInfo); - } -#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) - if (!foundFDE && (sects.dwarf_index_section != 0)) { - foundFDE = EHHeaderParser::findFDE( - _addressSpace, pc, sects.dwarf_index_section, - (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo); - } -#endif - if (!foundFDE) { - // otherwise, search cache of previously found FDEs. - pint_t cachedFDE = DwarfFDECache::findFDE(sects.dso_base, pc); - if (cachedFDE != 0) { - foundFDE = - CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, - (uint32_t)sects.dwarf_section_length, - cachedFDE, &fdeInfo, &cieInfo); - foundInCache = foundFDE; - } - } - if (!foundFDE) { - // Still not found, do full scan of __eh_frame section. - foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, - (uint32_t)sects.dwarf_section_length, 0, - &fdeInfo, &cieInfo); - } - if (foundFDE) { - typename CFI_Parser::PrologInfo prolog; - if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, - R::getArch(), &prolog)) { - // Save off parsed FDE info - _info.start_ip = fdeInfo.pcStart; - _info.end_ip = fdeInfo.pcEnd; - _info.lsda = fdeInfo.lsda; - _info.handler = cieInfo.personality; - _info.gp = prolog.spExtraArgSize; - _info.flags = 0; - _info.format = dwarfEncoding(); - _info.unwind_info = fdeInfo.fdeStart; - _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; - _info.extra = (unw_word_t) sects.dso_base; - - // Add to cache (to make next lookup faster) if we had no hint - // and there was no index. - if (!foundInCache && (fdeSectionOffsetHint == 0)) { - #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) - if (sects.dwarf_index_section == 0) - #endif - DwarfFDECache::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd, - fdeInfo.fdeStart); - } - return true; - } - } - //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc); - return false; -} -#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - - -#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) -template -bool UnwindCursor::getInfoFromCompactEncodingSection(pint_t pc, - const UnwindInfoSections §s) { - const bool log = false; - if (log) - fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n", - (uint64_t)pc, (uint64_t)sects.dso_base); - - const UnwindSectionHeader sectionHeader(_addressSpace, - sects.compact_unwind_section); - if (sectionHeader.version() != UNWIND_SECTION_VERSION) - return false; - - // do a binary search of top level index to find page with unwind info - pint_t targetFunctionOffset = pc - sects.dso_base; - const UnwindSectionIndexArray topIndex(_addressSpace, - sects.compact_unwind_section - + sectionHeader.indexSectionOffset()); - uint32_t low = 0; - uint32_t high = sectionHeader.indexCount(); - uint32_t last = high - 1; - while (low < high) { - uint32_t mid = (low + high) / 2; - //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n", - //mid, low, high, topIndex.functionOffset(mid)); - if (topIndex.functionOffset(mid) <= targetFunctionOffset) { - if ((mid == last) || - (topIndex.functionOffset(mid + 1) > targetFunctionOffset)) { - low = mid; - break; - } else { - low = mid + 1; - } - } else { - high = mid; - } - } - const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low); - const uint32_t firstLevelNextPageFunctionOffset = - topIndex.functionOffset(low + 1); - const pint_t secondLevelAddr = - sects.compact_unwind_section + topIndex.secondLevelPagesSectionOffset(low); - const pint_t lsdaArrayStartAddr = - sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low); - const pint_t lsdaArrayEndAddr = - sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low+1); - if (log) - fprintf(stderr, "\tfirst level search for result index=%d " - "to secondLevelAddr=0x%llX\n", - low, (uint64_t) secondLevelAddr); - // do a binary search of second level page index - uint32_t encoding = 0; - pint_t funcStart = 0; - pint_t funcEnd = 0; - pint_t lsda = 0; - pint_t personality = 0; - uint32_t pageKind = _addressSpace.get32(secondLevelAddr); - if (pageKind == UNWIND_SECOND_LEVEL_REGULAR) { - // regular page - UnwindSectionRegularPageHeader pageHeader(_addressSpace, - secondLevelAddr); - UnwindSectionRegularArray pageIndex( - _addressSpace, secondLevelAddr + pageHeader.entryPageOffset()); - // binary search looks for entry with e where index[e].offset <= pc < - // index[e+1].offset - if (log) - fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in " - "regular page starting at secondLevelAddr=0x%llX\n", - (uint64_t) targetFunctionOffset, (uint64_t) secondLevelAddr); - low = 0; - high = pageHeader.entryCount(); - while (low < high) { - uint32_t mid = (low + high) / 2; - if (pageIndex.functionOffset(mid) <= targetFunctionOffset) { - if (mid == (uint32_t)(pageHeader.entryCount() - 1)) { - // at end of table - low = mid; - funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base; - break; - } else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) { - // next is too big, so we found it - low = mid; - funcEnd = pageIndex.functionOffset(low + 1) + sects.dso_base; - break; - } else { - low = mid + 1; - } - } else { - high = mid; - } - } - encoding = pageIndex.encoding(low); - funcStart = pageIndex.functionOffset(low) + sects.dso_base; - if (pc < funcStart) { - if (log) - fprintf( - stderr, - "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", - (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd); - return false; - } - if (pc > funcEnd) { - if (log) - fprintf( - stderr, - "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", - (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd); - return false; - } - } else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) { - // compressed page - UnwindSectionCompressedPageHeader pageHeader(_addressSpace, - secondLevelAddr); - UnwindSectionCompressedArray pageIndex( - _addressSpace, secondLevelAddr + pageHeader.entryPageOffset()); - const uint32_t targetFunctionPageOffset = - (uint32_t)(targetFunctionOffset - firstLevelFunctionOffset); - // binary search looks for entry with e where index[e].offset <= pc < - // index[e+1].offset - if (log) - fprintf(stderr, "\tbinary search of compressed page starting at " - "secondLevelAddr=0x%llX\n", - (uint64_t) secondLevelAddr); - low = 0; - last = pageHeader.entryCount() - 1; - high = pageHeader.entryCount(); - while (low < high) { - uint32_t mid = (low + high) / 2; - if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) { - if ((mid == last) || - (pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) { - low = mid; - break; - } else { - low = mid + 1; - } - } else { - high = mid; - } - } - funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset - + sects.dso_base; - if (low < last) - funcEnd = - pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset - + sects.dso_base; - else - funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base; - if (pc < funcStart) { - _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " - "level compressed unwind table. funcStart=0x%llX", - (uint64_t) pc, (uint64_t) funcStart); - return false; - } - if (pc > funcEnd) { - _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " - "level compressed unwind table. funcEnd=0x%llX", - (uint64_t) pc, (uint64_t) funcEnd); - return false; - } - uint16_t encodingIndex = pageIndex.encodingIndex(low); - if (encodingIndex < sectionHeader.commonEncodingsArrayCount()) { - // encoding is in common table in section header - encoding = _addressSpace.get32( - sects.compact_unwind_section + - sectionHeader.commonEncodingsArraySectionOffset() + - encodingIndex * sizeof(uint32_t)); - } else { - // encoding is in page specific table - uint16_t pageEncodingIndex = - encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount(); - encoding = _addressSpace.get32(secondLevelAddr + - pageHeader.encodingsPageOffset() + - pageEncodingIndex * sizeof(uint32_t)); - } - } else { - _LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second " - "level page", - (uint64_t) sects.compact_unwind_section); - return false; - } - - // look up LSDA, if encoding says function has one - if (encoding & UNWIND_HAS_LSDA) { - UnwindSectionLsdaArray lsdaIndex(_addressSpace, lsdaArrayStartAddr); - uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base); - low = 0; - high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) / - sizeof(unwind_info_section_header_lsda_index_entry); - // binary search looks for entry with exact match for functionOffset - if (log) - fprintf(stderr, - "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n", - funcStartOffset); - while (low < high) { - uint32_t mid = (low + high) / 2; - if (lsdaIndex.functionOffset(mid) == funcStartOffset) { - lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base; - break; - } else if (lsdaIndex.functionOffset(mid) < funcStartOffset) { - low = mid + 1; - } else { - high = mid; - } - } - if (lsda == 0) { - _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for " - "pc=0x%0llX, but lsda table has no entry", - encoding, (uint64_t) pc); - return false; - } - } - - // extact personality routine, if encoding says function has one - uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >> - (__builtin_ctz(UNWIND_PERSONALITY_MASK)); - if (personalityIndex != 0) { - --personalityIndex; // change 1-based to zero-based index - if (personalityIndex > sectionHeader.personalityArrayCount()) { - _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, " - "but personality table has only %d entires", - encoding, personalityIndex, - sectionHeader.personalityArrayCount()); - return false; - } - int32_t personalityDelta = (int32_t)_addressSpace.get32( - sects.compact_unwind_section + - sectionHeader.personalityArraySectionOffset() + - personalityIndex * sizeof(uint32_t)); - pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta; - personality = _addressSpace.getP(personalityPointer); - if (log) - fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " - "personalityDelta=0x%08X, personality=0x%08llX\n", - (uint64_t) pc, personalityDelta, (uint64_t) personality); - } - - if (log) - fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " - "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n", - (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart); - _info.start_ip = funcStart; - _info.end_ip = funcEnd; - _info.lsda = lsda; - _info.handler = personality; - _info.gp = 0; - _info.flags = 0; - _info.format = encoding; - _info.unwind_info = 0; - _info.unwind_info_size = 0; - _info.extra = sects.dso_base; - return true; -} -#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) - - -#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) -template -bool UnwindCursor::getInfoFromSEH(pint_t pc) { - pint_t base; - RUNTIME_FUNCTION *unwindEntry = lookUpSEHUnwindInfo(pc, &base); - if (!unwindEntry) { - _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc); - return false; - } - _info.gp = 0; - _info.flags = 0; - _info.format = 0; - _info.unwind_info_size = sizeof(RUNTIME_FUNCTION); - _info.unwind_info = reinterpret_cast(unwindEntry); - _info.extra = base; - _info.start_ip = base + unwindEntry->BeginAddress; -#ifdef _LIBUNWIND_TARGET_X86_64 - _info.end_ip = base + unwindEntry->EndAddress; - // Only fill in the handler and LSDA if they're stale. - if (pc != getLastPC()) { - UNWIND_INFO *xdata = reinterpret_cast(base + unwindEntry->UnwindData); - if (xdata->Flags & (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER)) { - // The personality is given in the UNWIND_INFO itself. The LSDA immediately - // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit - // these structures.) - // N.B. UNWIND_INFO structs are DWORD-aligned. - uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1; - const uint32_t *handler = reinterpret_cast(&xdata->UnwindCodes[lastcode]); - _info.lsda = reinterpret_cast(handler+1); - if (*handler) { - _info.handler = reinterpret_cast(__libunwind_seh_personality); - } else - _info.handler = 0; - } else { - _info.lsda = 0; - _info.handler = 0; - } - } -#elif defined(_LIBUNWIND_TARGET_ARM) - _info.end_ip = _info.start_ip + unwindEntry->FunctionLength; - _info.lsda = 0; // FIXME - _info.handler = 0; // FIXME -#endif - setLastPC(pc); - return true; -} -#endif - - -template -void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { - pint_t pc = (pint_t)this->getReg(UNW_REG_IP); -#if defined(_LIBUNWIND_ARM_EHABI) - // Remove the thumb bit so the IP represents the actual instruction address. - // This matches the behaviour of _Unwind_GetIP on arm. - pc &= (pint_t)~0x1; -#endif - - // If the last line of a function is a "throw" the compiler sometimes - // emits no instructions after the call to __cxa_throw. This means - // the return address is actually the start of the next function. - // To disambiguate this, back up the pc when we know it is a return - // address. - if (isReturnAddress) - --pc; - - // Ask address space object to find unwind sections for this pc. - UnwindInfoSections sects; - if (_addressSpace.findUnwindSections(pc, sects)) { -#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) - // If there is a compact unwind encoding table, look there first. - if (sects.compact_unwind_section != 0) { - if (this->getInfoFromCompactEncodingSection(pc, sects)) { - #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - // Found info in table, done unless encoding says to use dwarf. - uint32_t dwarfOffset; - if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) { - if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) { - // found info in dwarf, done - return; - } - } - #endif - // If unwind table has entry, but entry says there is no unwind info, - // record that we have no unwind info. - if (_info.format == 0) - _unwindInfoMissing = true; - return; - } - } -#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) - -#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) - // If there is SEH unwind info, look there next. - if (this->getInfoFromSEH(pc)) - return; -#endif - -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - // If there is dwarf unwind info, look there next. - if (sects.dwarf_section != 0) { - if (this->getInfoFromDwarfSection(pc, sects)) { - // found info in dwarf, done - return; - } - } -#endif - -#if defined(_LIBUNWIND_ARM_EHABI) - // If there is ARM EHABI unwind info, look there next. - if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects)) - return; -#endif - } - -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - // There is no static unwind info for this pc. Look to see if an FDE was - // dynamically registered for it. - pint_t cachedFDE = DwarfFDECache::findFDE(0, pc); - if (cachedFDE != 0) { - CFI_Parser::FDE_Info fdeInfo; - CFI_Parser::CIE_Info cieInfo; - const char *msg = CFI_Parser::decodeFDE(_addressSpace, - cachedFDE, &fdeInfo, &cieInfo); - if (msg == NULL) { - typename CFI_Parser::PrologInfo prolog; - if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, - pc, R::getArch(), &prolog)) { - // save off parsed FDE info - _info.start_ip = fdeInfo.pcStart; - _info.end_ip = fdeInfo.pcEnd; - _info.lsda = fdeInfo.lsda; - _info.handler = cieInfo.personality; - _info.gp = prolog.spExtraArgSize; - // Some frameless functions need SP - // altered when resuming in function. - _info.flags = 0; - _info.format = dwarfEncoding(); - _info.unwind_info = fdeInfo.fdeStart; - _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; - _info.extra = 0; - return; - } - } - } - - // Lastly, ask AddressSpace object about platform specific ways to locate - // other FDEs. - pint_t fde; - if (_addressSpace.findOtherFDE(pc, fde)) { - CFI_Parser::FDE_Info fdeInfo; - CFI_Parser::CIE_Info cieInfo; - if (!CFI_Parser::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) { - // Double check this FDE is for a function that includes the pc. - if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) { - typename CFI_Parser::PrologInfo prolog; - if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, - pc, R::getArch(), &prolog)) { - // save off parsed FDE info - _info.start_ip = fdeInfo.pcStart; - _info.end_ip = fdeInfo.pcEnd; - _info.lsda = fdeInfo.lsda; - _info.handler = cieInfo.personality; - _info.gp = prolog.spExtraArgSize; - _info.flags = 0; - _info.format = dwarfEncoding(); - _info.unwind_info = fdeInfo.fdeStart; - _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; - _info.extra = 0; - return; - } - } - } - } -#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - - // no unwind info, flag that we can't reliably unwind - _unwindInfoMissing = true; -} - -template -int UnwindCursor::step() { - // Bottom of stack is defined is when unwind info cannot be found. - if (_unwindInfoMissing) - return UNW_STEP_END; - - // Use unwinding info to modify register set as if function returned. - int result; -#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) - result = this->stepWithCompactEncoding(); -#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) - result = this->stepWithSEHData(); -#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - result = this->stepWithDwarfFDE(); -#elif defined(_LIBUNWIND_ARM_EHABI) - result = this->stepWithEHABI(); -#else - #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \ - _LIBUNWIND_SUPPORT_SEH_UNWIND or \ - _LIBUNWIND_SUPPORT_DWARF_UNWIND or \ - _LIBUNWIND_ARM_EHABI -#endif - - // update info based on new PC - if (result == UNW_STEP_SUCCESS) { - this->setInfoBasedOnIPRegister(true); - if (_unwindInfoMissing) - return UNW_STEP_END; - } - - return result; -} - -template -void UnwindCursor::getInfo(unw_proc_info_t *info) { - *info = _info; -} - -template -bool UnwindCursor::getFunctionName(char *buf, size_t bufLen, - unw_word_t *offset) { - return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP), - buf, bufLen, offset); -} - -} // namespace libunwind - -#endif // __UNWINDCURSOR_HPP__ Index: head/contrib/llvm/projects/libunwind/src/RWMutex.hpp =================================================================== --- head/contrib/llvm/projects/libunwind/src/RWMutex.hpp (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/RWMutex.hpp (nonexistent) @@ -1,77 +0,0 @@ -//===----------------------------- Registers.hpp --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Abstract interface to shared reader/writer log, hiding platform and -// configuration differences. -// -//===----------------------------------------------------------------------===// - -#ifndef __RWMUTEX_HPP__ -#define __RWMUTEX_HPP__ - -#if defined(_WIN32) -#include -#elif !defined(_LIBUNWIND_HAS_NO_THREADS) -#include -#endif - -namespace libunwind { - -#if defined(_LIBUNWIND_HAS_NO_THREADS) - -class _LIBUNWIND_HIDDEN RWMutex { -public: - bool lock_shared() { return true; } - bool unlock_shared() { return true; } - bool lock() { return true; } - bool unlock() { return true; } -}; - -#elif defined(_WIN32) - -class _LIBUNWIND_HIDDEN RWMutex { -public: - bool lock_shared() { - AcquireSRWLockShared(&_lock); - return true; - } - bool unlock_shared() { - ReleaseSRWLockShared(&_lock); - return true; - } - bool lock() { - AcquireSRWLockExclusive(&_lock); - return true; - } - bool unlock() { - ReleaseSRWLockExclusive(&_lock); - return true; - } - -private: - SRWLOCK _lock = SRWLOCK_INIT; -}; - -#else - -class _LIBUNWIND_HIDDEN RWMutex { -public: - bool lock_shared() { return pthread_rwlock_rdlock(&_lock) == 0; } - bool unlock_shared() { return pthread_rwlock_unlock(&_lock) == 0; } - bool lock() { return pthread_rwlock_wrlock(&_lock) == 0; } - bool unlock() { return pthread_rwlock_unlock(&_lock) == 0; } - -private: - pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER; -}; - -#endif - -} // namespace libunwind - -#endif // __RWMUTEX_HPP__ Property changes on: head/contrib/llvm/projects/libunwind/src/RWMutex.hpp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/Unwind-seh.cpp =================================================================== --- head/contrib/llvm/projects/libunwind/src/Unwind-seh.cpp (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/Unwind-seh.cpp (nonexistent) @@ -1,491 +0,0 @@ -//===--------------------------- Unwind-seh.cpp ---------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Implements SEH-based Itanium C++ exceptions. -// -//===----------------------------------------------------------------------===// - -#include "config.h" - -#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) - -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "libunwind_ext.h" -#include "UnwindCursor.hpp" - -using namespace libunwind; - -#define STATUS_USER_DEFINED (1u << 29) - -#define STATUS_GCC_MAGIC (('G' << 16) | ('C' << 8) | 'C') - -#define MAKE_CUSTOM_STATUS(s, c) \ - ((NTSTATUS)(((s) << 30) | STATUS_USER_DEFINED | (c))) -#define MAKE_GCC_EXCEPTION(c) \ - MAKE_CUSTOM_STATUS(STATUS_SEVERITY_SUCCESS, STATUS_GCC_MAGIC | ((c) << 24)) - -/// SEH exception raised by libunwind when the program calls -/// \c _Unwind_RaiseException. -#define STATUS_GCC_THROW MAKE_GCC_EXCEPTION(0) // 0x20474343 -/// SEH exception raised by libunwind to initiate phase 2 of exception -/// handling. -#define STATUS_GCC_UNWIND MAKE_GCC_EXCEPTION(1) // 0x21474343 - -/// Class of foreign exceptions based on unrecognized SEH exceptions. -static const uint64_t kSEHExceptionClass = 0x434C4E4753454800; // CLNGSEH\0 - -/// Exception cleanup routine used by \c _GCC_specific_handler to -/// free foreign exceptions. -static void seh_exc_cleanup(_Unwind_Reason_Code urc, _Unwind_Exception *exc) { - if (exc->exception_class != kSEHExceptionClass) - _LIBUNWIND_ABORT("SEH cleanup called on non-SEH exception"); - free(exc); -} - -static int _unw_init_seh(unw_cursor_t *cursor, CONTEXT *ctx); -static DISPATCHER_CONTEXT *_unw_seh_get_disp_ctx(unw_cursor_t *cursor); -static void _unw_seh_set_disp_ctx(unw_cursor_t *cursor, DISPATCHER_CONTEXT *disp); - -/// Common implementation of SEH-style handler functions used by Itanium- -/// style frames. Depending on how and why it was called, it may do one of: -/// a) Delegate to the given Itanium-style personality function; or -/// b) Initiate a collided unwind to halt unwinding. -_LIBUNWIND_EXPORT EXCEPTION_DISPOSITION -_GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, - DISPATCHER_CONTEXT *disp, __personality_routine pers) { - unw_context_t uc; - unw_cursor_t cursor; - _Unwind_Exception *exc; - _Unwind_Action action; - struct _Unwind_Context *ctx = nullptr; - _Unwind_Reason_Code urc; - uintptr_t retval, target; - bool ours = false; - - _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler(%#010x(%x), %p)", ms_exc->ExceptionCode, ms_exc->ExceptionFlags, frame); - if (ms_exc->ExceptionCode == STATUS_GCC_UNWIND) { - if (IS_TARGET_UNWIND(ms_exc->ExceptionFlags)) { - // Set up the upper return value (the lower one and the target PC - // were set in the call to RtlUnwindEx()) for the landing pad. -#ifdef __x86_64__ - disp->ContextRecord->Rdx = ms_exc->ExceptionInformation[3]; -#elif defined(__arm__) - disp->ContextRecord->R1 = ms_exc->ExceptionInformation[3]; -#elif defined(__aarch64__) - disp->ContextRecord->X1 = ms_exc->ExceptionInformation[3]; -#endif - } - // This is the collided unwind to the landing pad. Nothing to do. - return ExceptionContinueSearch; - } - - if (ms_exc->ExceptionCode == STATUS_GCC_THROW) { - // This is (probably) a libunwind-controlled exception/unwind. Recover the - // parameters which we set below, and pass them to the personality function. - ours = true; - exc = (_Unwind_Exception *)ms_exc->ExceptionInformation[0]; - if (!IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) { - ctx = (struct _Unwind_Context *)ms_exc->ExceptionInformation[1]; - action = (_Unwind_Action)ms_exc->ExceptionInformation[2]; - } - } else { - // Foreign exception. - exc = (_Unwind_Exception *)malloc(sizeof(_Unwind_Exception)); - exc->exception_class = kSEHExceptionClass; - exc->exception_cleanup = seh_exc_cleanup; - memset(exc->private_, 0, sizeof(exc->private_)); - } - if (!ctx) { - _unw_init_seh(&cursor, disp->ContextRecord); - _unw_seh_set_disp_ctx(&cursor, disp); - unw_set_reg(&cursor, UNW_REG_IP, disp->ControlPc-1); - ctx = (struct _Unwind_Context *)&cursor; - - if (!IS_UNWINDING(ms_exc->ExceptionFlags)) { - if (ours && ms_exc->NumberParameters > 1) - action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_FORCE_UNWIND); - else - action = _UA_SEARCH_PHASE; - } else { - if (ours && ms_exc->ExceptionInformation[1] == (ULONG_PTR)frame) - action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME); - else - action = _UA_CLEANUP_PHASE; - } - } - - _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() calling personality function %p(1, %d, %llx, %p, %p)", pers, action, exc->exception_class, exc, ctx); - urc = pers(1, action, exc->exception_class, exc, ctx); - _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() personality returned %d", urc); - switch (urc) { - case _URC_CONTINUE_UNWIND: - // If we're in phase 2, and the personality routine said to continue - // at the target frame, we're in real trouble. - if (action & _UA_HANDLER_FRAME) - _LIBUNWIND_ABORT("Personality continued unwind at the target frame!"); - return ExceptionContinueSearch; - case _URC_HANDLER_FOUND: - // If we were called by __libunwind_seh_personality(), indicate that - // a handler was found; otherwise, initiate phase 2 by unwinding. - if (ours && ms_exc->NumberParameters > 1) - return 4 /* ExecptionExecuteHandler in mingw */; - // This should never happen in phase 2. - if (IS_UNWINDING(ms_exc->ExceptionFlags)) - _LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!"); - exc->private_[1] = (ULONG_PTR)frame; - if (ours) { - ms_exc->NumberParameters = 4; - ms_exc->ExceptionInformation[1] = (ULONG_PTR)frame; - } - // FIXME: Indicate target frame in foreign case! - // phase 2: the clean up phase - RtlUnwindEx(frame, (PVOID)disp->ControlPc, ms_exc, exc, ms_ctx, disp->HistoryTable); - _LIBUNWIND_ABORT("RtlUnwindEx() failed"); - case _URC_INSTALL_CONTEXT: { - // If we were called by __libunwind_seh_personality(), indicate that - // a handler was found; otherwise, it's time to initiate a collided - // unwind to the target. - if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) - return 4 /* ExecptionExecuteHandler in mingw */; - // This should never happen in phase 1. - if (!IS_UNWINDING(ms_exc->ExceptionFlags)) - _LIBUNWIND_ABORT("Personality installed context during phase 1!"); -#ifdef __x86_64__ - exc->private_[2] = disp->TargetIp; - unw_get_reg(&cursor, UNW_X86_64_RAX, &retval); - unw_get_reg(&cursor, UNW_X86_64_RDX, &exc->private_[3]); -#elif defined(__arm__) - exc->private_[2] = disp->TargetPc; - unw_get_reg(&cursor, UNW_ARM_R0, &retval); - unw_get_reg(&cursor, UNW_ARM_R1, &exc->private_[3]); -#elif defined(__aarch64__) - exc->private_[2] = disp->TargetPc; - unw_get_reg(&cursor, UNW_ARM64_X0, &retval); - unw_get_reg(&cursor, UNW_ARM64_X1, &exc->private_[3]); -#endif - unw_get_reg(&cursor, UNW_REG_IP, &target); - ms_exc->ExceptionCode = STATUS_GCC_UNWIND; -#ifdef __x86_64__ - ms_exc->ExceptionInformation[2] = disp->TargetIp; -#elif defined(__arm__) || defined(__aarch64__) - ms_exc->ExceptionInformation[2] = disp->TargetPc; -#endif - ms_exc->ExceptionInformation[3] = exc->private_[3]; - // Give NTRTL some scratch space to keep track of the collided unwind. - // Don't use the one that was passed in; we don't want to overwrite the - // context in the DISPATCHER_CONTEXT. - CONTEXT new_ctx; - RtlUnwindEx(frame, (PVOID)target, ms_exc, (PVOID)retval, &new_ctx, disp->HistoryTable); - _LIBUNWIND_ABORT("RtlUnwindEx() failed"); - } - // Anything else indicates a serious problem. - default: return ExceptionContinueExecution; - } -} - -/// Personality function returned by \c unw_get_proc_info() in SEH contexts. -/// This is a wrapper that calls the real SEH handler function, which in -/// turn (at least, for Itanium-style frames) calls the real Itanium -/// personality function (see \c _GCC_specific_handler()). -extern "C" _Unwind_Reason_Code -__libunwind_seh_personality(int version, _Unwind_Action state, - uint64_t klass, _Unwind_Exception *exc, - struct _Unwind_Context *context) { - EXCEPTION_RECORD ms_exc; - bool phase2 = (state & (_UA_SEARCH_PHASE|_UA_CLEANUP_PHASE)) == _UA_CLEANUP_PHASE; - ms_exc.ExceptionCode = STATUS_GCC_THROW; - ms_exc.ExceptionFlags = 0; - ms_exc.NumberParameters = 3; - ms_exc.ExceptionInformation[0] = (ULONG_PTR)exc; - ms_exc.ExceptionInformation[1] = (ULONG_PTR)context; - ms_exc.ExceptionInformation[2] = state; - DISPATCHER_CONTEXT *disp_ctx = _unw_seh_get_disp_ctx((unw_cursor_t *)context); - EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc, - (PVOID)disp_ctx->EstablisherFrame, - disp_ctx->ContextRecord, - disp_ctx); - switch (ms_act) { - case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND; - case 4 /*ExceptionExecuteHandler*/: - return phase2 ? _URC_INSTALL_CONTEXT : _URC_HANDLER_FOUND; - default: - return phase2 ? _URC_FATAL_PHASE2_ERROR : _URC_FATAL_PHASE1_ERROR; - } -} - -static _Unwind_Reason_Code -unwind_phase2_forced(unw_context_t *uc, - _Unwind_Exception *exception_object, - _Unwind_Stop_Fn stop, void *stop_parameter) { - unw_cursor_t cursor2; - unw_init_local(&cursor2, uc); - - // Walk each frame until we reach where search phase said to stop - while (unw_step(&cursor2) > 0) { - - // Update info about this frame. - unw_proc_info_t frameInfo; - if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step " - "failed => _URC_END_OF_STACK", - (void *)exception_object); - return _URC_FATAL_PHASE2_ERROR; - } - - // When tracing, print state information. - if (_LIBUNWIND_TRACING_UNWINDING) { - char functionBuf[512]; - const char *functionName = functionBuf; - unw_word_t offset; - if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf), - &offset) != UNW_ESUCCESS) || - (frameInfo.start_ip + offset > frameInfo.end_ip)) - functionName = ".anonymous."; - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64 - ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64, - (void *)exception_object, frameInfo.start_ip, functionName, - frameInfo.lsda, frameInfo.handler); - } - - // Call stop function at each frame. - _Unwind_Action action = - (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); - _Unwind_Reason_Code stopResult = - (*stop)(1, action, exception_object->exception_class, exception_object, - (struct _Unwind_Context *)(&cursor2), stop_parameter); - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): stop function returned %d", - (void *)exception_object, stopResult); - if (stopResult != _URC_NO_REASON) { - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): stopped by stop function", - (void *)exception_object); - return _URC_FATAL_PHASE2_ERROR; - } - - // If there is a personality routine, tell it we are unwinding. - if (frameInfo.handler != 0) { - __personality_routine p = - (__personality_routine)(intptr_t)(frameInfo.handler); - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", - (void *)exception_object, (void *)(uintptr_t)p); - _Unwind_Reason_Code personalityResult = - (*p)(1, action, exception_object->exception_class, exception_object, - (struct _Unwind_Context *)(&cursor2)); - switch (personalityResult) { - case _URC_CONTINUE_UNWIND: - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "personality returned " - "_URC_CONTINUE_UNWIND", - (void *)exception_object); - // Destructors called, continue unwinding - break; - case _URC_INSTALL_CONTEXT: - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "personality returned " - "_URC_INSTALL_CONTEXT", - (void *)exception_object); - // We may get control back if landing pad calls _Unwind_Resume(). - unw_resume(&cursor2); - break; - default: - // Personality routine returned an unknown result code. - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "personality returned %d, " - "_URC_FATAL_PHASE2_ERROR", - (void *)exception_object, personalityResult); - return _URC_FATAL_PHASE2_ERROR; - } - } - } - - // Call stop function one last time and tell it we've reached the end - // of the stack. - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " - "function with _UA_END_OF_STACK", - (void *)exception_object); - _Unwind_Action lastAction = - (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); - (*stop)(1, lastAction, exception_object->exception_class, exception_object, - (struct _Unwind_Context *)(&cursor2), stop_parameter); - - // Clean up phase did not resume at the frame that the search phase said it - // would. - return _URC_FATAL_PHASE2_ERROR; -} - -/// Called by \c __cxa_throw(). Only returns if there is a fatal error. -_LIBUNWIND_EXPORT _Unwind_Reason_Code -_Unwind_RaiseException(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)", - (void *)exception_object); - - // Mark that this is a non-forced unwind, so _Unwind_Resume() - // can do the right thing. - memset(exception_object->private_, 0, sizeof(exception_object->private_)); - - // phase 1: the search phase - // We'll let the system do that for us. - RaiseException(STATUS_GCC_THROW, 0, 1, (ULONG_PTR *)&exception_object); - - // If we get here, either something went horribly wrong or we reached the - // top of the stack. Either way, let libc++abi call std::terminate(). - return _URC_END_OF_STACK; -} - -/// When \c _Unwind_RaiseException() is in phase2, it hands control -/// to the personality function at each frame. The personality -/// may force a jump to a landing pad in that function; the landing -/// pad code may then call \c _Unwind_Resume() to continue with the -/// unwinding. Note: the call to \c _Unwind_Resume() is from compiler -/// geneated user code. All other \c _Unwind_* routines are called -/// by the C++ runtime \c __cxa_* routines. -/// -/// Note: re-throwing an exception (as opposed to continuing the unwind) -/// is implemented by having the code call \c __cxa_rethrow() which -/// in turn calls \c _Unwind_Resume_or_Rethrow(). -_LIBUNWIND_EXPORT void -_Unwind_Resume(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object); - - if (exception_object->private_[0] != 0) { - unw_context_t uc; - - unw_getcontext(&uc); - unwind_phase2_forced(&uc, exception_object, - (_Unwind_Stop_Fn) exception_object->private_[0], - (void *)exception_object->private_[4]); - } else { - // Recover the parameters for the unwind from the exception object - // so we can start unwinding again. - EXCEPTION_RECORD ms_exc; - CONTEXT ms_ctx; - UNWIND_HISTORY_TABLE hist; - - memset(&ms_exc, 0, sizeof(ms_exc)); - memset(&hist, 0, sizeof(hist)); - ms_exc.ExceptionCode = STATUS_GCC_THROW; - ms_exc.ExceptionFlags = EXCEPTION_NONCONTINUABLE; - ms_exc.NumberParameters = 4; - ms_exc.ExceptionInformation[0] = (ULONG_PTR)exception_object; - ms_exc.ExceptionInformation[1] = exception_object->private_[1]; - ms_exc.ExceptionInformation[2] = exception_object->private_[2]; - ms_exc.ExceptionInformation[3] = exception_object->private_[3]; - RtlUnwindEx((PVOID)exception_object->private_[1], - (PVOID)exception_object->private_[2], &ms_exc, - exception_object, &ms_ctx, &hist); - } - - // Clients assume _Unwind_Resume() does not return, so all we can do is abort. - _LIBUNWIND_ABORT("_Unwind_Resume() can't return"); -} - -/// Not used by C++. -/// Unwinds stack, calling "stop" function at each frame. -/// Could be used to implement \c longjmp(). -_LIBUNWIND_EXPORT _Unwind_Reason_Code -_Unwind_ForcedUnwind(_Unwind_Exception *exception_object, - _Unwind_Stop_Fn stop, void *stop_parameter) { - _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)", - (void *)exception_object, (void *)(uintptr_t)stop); - unw_context_t uc; - unw_getcontext(&uc); - - // Mark that this is a forced unwind, so _Unwind_Resume() can do - // the right thing. - exception_object->private_[0] = (uintptr_t) stop; - exception_object->private_[4] = (uintptr_t) stop_parameter; - - // do it - return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter); -} - -/// Called by personality handler during phase 2 to get LSDA for current frame. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { - uintptr_t result = (uintptr_t)_unw_seh_get_disp_ctx((unw_cursor_t *)context)->HandlerData; - _LIBUNWIND_TRACE_API( - "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR, - (void *)context, result); - return result; -} - -/// Called by personality handler during phase 2 to find the start of the -/// function. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetRegionStart(struct _Unwind_Context *context) { - DISPATCHER_CONTEXT *disp = _unw_seh_get_disp_ctx((unw_cursor_t *)context); - uintptr_t result = (uintptr_t)disp->FunctionEntry->BeginAddress + disp->ImageBase; - _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR, - (void *)context, result); - return result; -} - -static int -_unw_init_seh(unw_cursor_t *cursor, CONTEXT *context) { -#ifdef _LIBUNWIND_TARGET_X86_64 - new ((void *)cursor) UnwindCursor( - context, LocalAddressSpace::sThisAddressSpace); - auto *co = reinterpret_cast(cursor); - co->setInfoBasedOnIPRegister(); - return UNW_ESUCCESS; -#elif defined(_LIBUNWIND_TARGET_ARM) - new ((void *)cursor) UnwindCursor( - context, LocalAddressSpace::sThisAddressSpace); - auto *co = reinterpret_cast(cursor); - co->setInfoBasedOnIPRegister(); - return UNW_ESUCCESS; -#elif defined(_LIBUNWIND_TARGET_AARCH64) - new ((void *)cursor) UnwindCursor( - context, LocalAddressSpace::sThisAddressSpace); - auto *co = reinterpret_cast(cursor); - co->setInfoBasedOnIPRegister(); - return UNW_ESUCCESS; -#else - return UNW_EINVAL; -#endif -} - -static DISPATCHER_CONTEXT * -_unw_seh_get_disp_ctx(unw_cursor_t *cursor) { -#ifdef _LIBUNWIND_TARGET_X86_64 - return reinterpret_cast *>(cursor)->getDispatcherContext(); -#elif defined(_LIBUNWIND_TARGET_ARM) - return reinterpret_cast *>(cursor)->getDispatcherContext(); -#elif defined(_LIBUNWIND_TARGET_AARCH64) - return reinterpret_cast *>(cursor)->getDispatcherContext(); -#else - return nullptr; -#endif -} - -static void -_unw_seh_set_disp_ctx(unw_cursor_t *cursor, DISPATCHER_CONTEXT *disp) { -#ifdef _LIBUNWIND_TARGET_X86_64 - reinterpret_cast *>(cursor)->setDispatcherContext(disp); -#elif defined(_LIBUNWIND_TARGET_ARM) - reinterpret_cast *>(cursor)->setDispatcherContext(disp); -#elif defined(_LIBUNWIND_TARGET_AARCH64) - reinterpret_cast *>(cursor)->setDispatcherContext(disp); -#endif -} - -#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) Property changes on: head/contrib/llvm/projects/libunwind/src/Unwind-seh.cpp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/dwarf2.h =================================================================== --- head/contrib/llvm/projects/libunwind/src/dwarf2.h (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/dwarf2.h (nonexistent) @@ -1,240 +0,0 @@ -//===------------------------------- dwarf2.h -----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - - -/* - These constants were taken from version 3 of the DWARF standard, - which is Copyright (c) 2005 Free Standards Group, and - Copyright (c) 1992, 1993 UNIX International, Inc. -*/ - -#ifndef __DWARF2__ -#define __DWARF2__ - -// DWARF unwind instructions -enum { - DW_CFA_nop = 0x0, - DW_CFA_set_loc = 0x1, - DW_CFA_advance_loc1 = 0x2, - DW_CFA_advance_loc2 = 0x3, - DW_CFA_advance_loc4 = 0x4, - DW_CFA_offset_extended = 0x5, - DW_CFA_restore_extended = 0x6, - DW_CFA_undefined = 0x7, - DW_CFA_same_value = 0x8, - DW_CFA_register = 0x9, - DW_CFA_remember_state = 0xA, - DW_CFA_restore_state = 0xB, - DW_CFA_def_cfa = 0xC, - DW_CFA_def_cfa_register = 0xD, - DW_CFA_def_cfa_offset = 0xE, - DW_CFA_def_cfa_expression = 0xF, - DW_CFA_expression = 0x10, - DW_CFA_offset_extended_sf = 0x11, - DW_CFA_def_cfa_sf = 0x12, - DW_CFA_def_cfa_offset_sf = 0x13, - DW_CFA_val_offset = 0x14, - DW_CFA_val_offset_sf = 0x15, - DW_CFA_val_expression = 0x16, - DW_CFA_advance_loc = 0x40, // high 2 bits are 0x1, lower 6 bits are delta - DW_CFA_offset = 0x80, // high 2 bits are 0x2, lower 6 bits are register - DW_CFA_restore = 0xC0, // high 2 bits are 0x3, lower 6 bits are register - - // GNU extensions - DW_CFA_GNU_window_save = 0x2D, - DW_CFA_GNU_args_size = 0x2E, - DW_CFA_GNU_negative_offset_extended = 0x2F, - - // AARCH64 extensions - DW_CFA_AARCH64_negate_ra_state = 0x2D -}; - - -// FSF exception handling Pointer-Encoding constants -// Used in CFI augmentation by GCC -enum { - DW_EH_PE_ptr = 0x00, - DW_EH_PE_uleb128 = 0x01, - DW_EH_PE_udata2 = 0x02, - DW_EH_PE_udata4 = 0x03, - DW_EH_PE_udata8 = 0x04, - DW_EH_PE_signed = 0x08, - DW_EH_PE_sleb128 = 0x09, - DW_EH_PE_sdata2 = 0x0A, - DW_EH_PE_sdata4 = 0x0B, - DW_EH_PE_sdata8 = 0x0C, - DW_EH_PE_absptr = 0x00, - DW_EH_PE_pcrel = 0x10, - DW_EH_PE_textrel = 0x20, - DW_EH_PE_datarel = 0x30, - DW_EH_PE_funcrel = 0x40, - DW_EH_PE_aligned = 0x50, - DW_EH_PE_indirect = 0x80, - DW_EH_PE_omit = 0xFF -}; - - -// DWARF expressions -enum { - DW_OP_addr = 0x03, // constant address (size target specific) - DW_OP_deref = 0x06, - DW_OP_const1u = 0x08, // 1-byte constant - DW_OP_const1s = 0x09, // 1-byte constant - DW_OP_const2u = 0x0A, // 2-byte constant - DW_OP_const2s = 0x0B, // 2-byte constant - DW_OP_const4u = 0x0C, // 4-byte constant - DW_OP_const4s = 0x0D, // 4-byte constant - DW_OP_const8u = 0x0E, // 8-byte constant - DW_OP_const8s = 0x0F, // 8-byte constant - DW_OP_constu = 0x10, // ULEB128 constant - DW_OP_consts = 0x11, // SLEB128 constant - DW_OP_dup = 0x12, - DW_OP_drop = 0x13, - DW_OP_over = 0x14, - DW_OP_pick = 0x15, // 1-byte stack index - DW_OP_swap = 0x16, - DW_OP_rot = 0x17, - DW_OP_xderef = 0x18, - DW_OP_abs = 0x19, - DW_OP_and = 0x1A, - DW_OP_div = 0x1B, - DW_OP_minus = 0x1C, - DW_OP_mod = 0x1D, - DW_OP_mul = 0x1E, - DW_OP_neg = 0x1F, - DW_OP_not = 0x20, - DW_OP_or = 0x21, - DW_OP_plus = 0x22, - DW_OP_plus_uconst = 0x23, // ULEB128 addend - DW_OP_shl = 0x24, - DW_OP_shr = 0x25, - DW_OP_shra = 0x26, - DW_OP_xor = 0x27, - DW_OP_skip = 0x2F, // signed 2-byte constant - DW_OP_bra = 0x28, // signed 2-byte constant - DW_OP_eq = 0x29, - DW_OP_ge = 0x2A, - DW_OP_gt = 0x2B, - DW_OP_le = 0x2C, - DW_OP_lt = 0x2D, - DW_OP_ne = 0x2E, - DW_OP_lit0 = 0x30, // Literal 0 - DW_OP_lit1 = 0x31, // Literal 1 - DW_OP_lit2 = 0x32, // Literal 2 - DW_OP_lit3 = 0x33, // Literal 3 - DW_OP_lit4 = 0x34, // Literal 4 - DW_OP_lit5 = 0x35, // Literal 5 - DW_OP_lit6 = 0x36, // Literal 6 - DW_OP_lit7 = 0x37, // Literal 7 - DW_OP_lit8 = 0x38, // Literal 8 - DW_OP_lit9 = 0x39, // Literal 9 - DW_OP_lit10 = 0x3A, // Literal 10 - DW_OP_lit11 = 0x3B, // Literal 11 - DW_OP_lit12 = 0x3C, // Literal 12 - DW_OP_lit13 = 0x3D, // Literal 13 - DW_OP_lit14 = 0x3E, // Literal 14 - DW_OP_lit15 = 0x3F, // Literal 15 - DW_OP_lit16 = 0x40, // Literal 16 - DW_OP_lit17 = 0x41, // Literal 17 - DW_OP_lit18 = 0x42, // Literal 18 - DW_OP_lit19 = 0x43, // Literal 19 - DW_OP_lit20 = 0x44, // Literal 20 - DW_OP_lit21 = 0x45, // Literal 21 - DW_OP_lit22 = 0x46, // Literal 22 - DW_OP_lit23 = 0x47, // Literal 23 - DW_OP_lit24 = 0x48, // Literal 24 - DW_OP_lit25 = 0x49, // Literal 25 - DW_OP_lit26 = 0x4A, // Literal 26 - DW_OP_lit27 = 0x4B, // Literal 27 - DW_OP_lit28 = 0x4C, // Literal 28 - DW_OP_lit29 = 0x4D, // Literal 29 - DW_OP_lit30 = 0x4E, // Literal 30 - DW_OP_lit31 = 0x4F, // Literal 31 - DW_OP_reg0 = 0x50, // Contents of reg0 - DW_OP_reg1 = 0x51, // Contents of reg1 - DW_OP_reg2 = 0x52, // Contents of reg2 - DW_OP_reg3 = 0x53, // Contents of reg3 - DW_OP_reg4 = 0x54, // Contents of reg4 - DW_OP_reg5 = 0x55, // Contents of reg5 - DW_OP_reg6 = 0x56, // Contents of reg6 - DW_OP_reg7 = 0x57, // Contents of reg7 - DW_OP_reg8 = 0x58, // Contents of reg8 - DW_OP_reg9 = 0x59, // Contents of reg9 - DW_OP_reg10 = 0x5A, // Contents of reg10 - DW_OP_reg11 = 0x5B, // Contents of reg11 - DW_OP_reg12 = 0x5C, // Contents of reg12 - DW_OP_reg13 = 0x5D, // Contents of reg13 - DW_OP_reg14 = 0x5E, // Contents of reg14 - DW_OP_reg15 = 0x5F, // Contents of reg15 - DW_OP_reg16 = 0x60, // Contents of reg16 - DW_OP_reg17 = 0x61, // Contents of reg17 - DW_OP_reg18 = 0x62, // Contents of reg18 - DW_OP_reg19 = 0x63, // Contents of reg19 - DW_OP_reg20 = 0x64, // Contents of reg20 - DW_OP_reg21 = 0x65, // Contents of reg21 - DW_OP_reg22 = 0x66, // Contents of reg22 - DW_OP_reg23 = 0x67, // Contents of reg23 - DW_OP_reg24 = 0x68, // Contents of reg24 - DW_OP_reg25 = 0x69, // Contents of reg25 - DW_OP_reg26 = 0x6A, // Contents of reg26 - DW_OP_reg27 = 0x6B, // Contents of reg27 - DW_OP_reg28 = 0x6C, // Contents of reg28 - DW_OP_reg29 = 0x6D, // Contents of reg29 - DW_OP_reg30 = 0x6E, // Contents of reg30 - DW_OP_reg31 = 0x6F, // Contents of reg31 - DW_OP_breg0 = 0x70, // base register 0 + SLEB128 offset - DW_OP_breg1 = 0x71, // base register 1 + SLEB128 offset - DW_OP_breg2 = 0x72, // base register 2 + SLEB128 offset - DW_OP_breg3 = 0x73, // base register 3 + SLEB128 offset - DW_OP_breg4 = 0x74, // base register 4 + SLEB128 offset - DW_OP_breg5 = 0x75, // base register 5 + SLEB128 offset - DW_OP_breg6 = 0x76, // base register 6 + SLEB128 offset - DW_OP_breg7 = 0x77, // base register 7 + SLEB128 offset - DW_OP_breg8 = 0x78, // base register 8 + SLEB128 offset - DW_OP_breg9 = 0x79, // base register 9 + SLEB128 offset - DW_OP_breg10 = 0x7A, // base register 10 + SLEB128 offset - DW_OP_breg11 = 0x7B, // base register 11 + SLEB128 offset - DW_OP_breg12 = 0x7C, // base register 12 + SLEB128 offset - DW_OP_breg13 = 0x7D, // base register 13 + SLEB128 offset - DW_OP_breg14 = 0x7E, // base register 14 + SLEB128 offset - DW_OP_breg15 = 0x7F, // base register 15 + SLEB128 offset - DW_OP_breg16 = 0x80, // base register 16 + SLEB128 offset - DW_OP_breg17 = 0x81, // base register 17 + SLEB128 offset - DW_OP_breg18 = 0x82, // base register 18 + SLEB128 offset - DW_OP_breg19 = 0x83, // base register 19 + SLEB128 offset - DW_OP_breg20 = 0x84, // base register 20 + SLEB128 offset - DW_OP_breg21 = 0x85, // base register 21 + SLEB128 offset - DW_OP_breg22 = 0x86, // base register 22 + SLEB128 offset - DW_OP_breg23 = 0x87, // base register 23 + SLEB128 offset - DW_OP_breg24 = 0x88, // base register 24 + SLEB128 offset - DW_OP_breg25 = 0x89, // base register 25 + SLEB128 offset - DW_OP_breg26 = 0x8A, // base register 26 + SLEB128 offset - DW_OP_breg27 = 0x8B, // base register 27 + SLEB128 offset - DW_OP_breg28 = 0x8C, // base register 28 + SLEB128 offset - DW_OP_breg29 = 0x8D, // base register 29 + SLEB128 offset - DW_OP_breg30 = 0x8E, // base register 30 + SLEB128 offset - DW_OP_breg31 = 0x8F, // base register 31 + SLEB128 offset - DW_OP_regx = 0x90, // ULEB128 register - DW_OP_fbreg = 0x91, // SLEB128 offset - DW_OP_bregx = 0x92, // ULEB128 register followed by SLEB128 offset - DW_OP_piece = 0x93, // ULEB128 size of piece addressed - DW_OP_deref_size = 0x94, // 1-byte size of data retrieved - DW_OP_xderef_size = 0x95, // 1-byte size of data retrieved - DW_OP_nop = 0x96, - DW_OP_push_object_addres = 0x97, - DW_OP_call2 = 0x98, // 2-byte offset of DIE - DW_OP_call4 = 0x99, // 4-byte offset of DIE - DW_OP_call_ref = 0x9A, // 4- or 8-byte offset of DIE - DW_OP_lo_user = 0xE0, - DW_OP_APPLE_uninit = 0xF0, - DW_OP_hi_user = 0xFF -}; - - -#endif Property changes on: head/contrib/llvm/projects/libunwind/src/dwarf2.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/assembly.h =================================================================== --- head/contrib/llvm/projects/libunwind/src/assembly.h (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/assembly.h (nonexistent) @@ -1,124 +0,0 @@ -/* ===-- assembly.h - libUnwind assembler support macros -------------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===----------------------------------------------------------------------=== - * - * This file defines macros for use in libUnwind assembler source. - * This file is not part of the interface of this library. - * - * ===----------------------------------------------------------------------=== - */ - -#ifndef UNWIND_ASSEMBLY_H -#define UNWIND_ASSEMBLY_H - -#if defined(__powerpc64__) -#define SEPARATOR ; -#define PPC64_OFFS_SRR0 0 -#define PPC64_OFFS_CR 272 -#define PPC64_OFFS_XER 280 -#define PPC64_OFFS_LR 288 -#define PPC64_OFFS_CTR 296 -#define PPC64_OFFS_VRSAVE 304 -#define PPC64_OFFS_FP 312 -#define PPC64_OFFS_V 824 -#ifdef _ARCH_PWR8 -#define PPC64_HAS_VMX -#endif -#elif defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__) -#define SEPARATOR @ -#elif defined(__arm64__) -#define SEPARATOR %% -#else -#define SEPARATOR ; -#endif - -#define GLUE2(a, b) a ## b -#define GLUE(a, b) GLUE2(a, b) -#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name) - -#if defined(__APPLE__) - -#define SYMBOL_IS_FUNC(name) -#define EXPORT_SYMBOL(name) -#define HIDDEN_SYMBOL(name) .private_extern name -#define NO_EXEC_STACK_DIRECTIVE - -#elif defined(__ELF__) - -#if defined(__arm__) -#define SYMBOL_IS_FUNC(name) .type name,%function -#else -#define SYMBOL_IS_FUNC(name) .type name,@function -#endif -#define EXPORT_SYMBOL(name) -#define HIDDEN_SYMBOL(name) .hidden name - -#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \ - defined(__linux__) -#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits -#else -#define NO_EXEC_STACK_DIRECTIVE -#endif - -#elif defined(_WIN32) - -#define SYMBOL_IS_FUNC(name) \ - .def name SEPARATOR \ - .scl 2 SEPARATOR \ - .type 32 SEPARATOR \ - .endef -#define EXPORT_SYMBOL2(name) \ - .section .drectve,"yn" SEPARATOR \ - .ascii "-export:", #name, "\0" SEPARATOR \ - .text -#if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS) -#define EXPORT_SYMBOL(name) -#else -#define EXPORT_SYMBOL(name) EXPORT_SYMBOL2(name) -#endif -#define HIDDEN_SYMBOL(name) - -#define NO_EXEC_STACK_DIRECTIVE - -#elif defined(__sparc__) - -#else - -#error Unsupported target - -#endif - -#define DEFINE_LIBUNWIND_FUNCTION(name) \ - .globl SYMBOL_NAME(name) SEPARATOR \ - EXPORT_SYMBOL(name) SEPARATOR \ - SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ - SYMBOL_NAME(name): - -#define DEFINE_LIBUNWIND_PRIVATE_FUNCTION(name) \ - .globl SYMBOL_NAME(name) SEPARATOR \ - HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \ - SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ - SYMBOL_NAME(name): - -#if defined(__arm__) -#if !defined(__ARM_ARCH) -#define __ARM_ARCH 4 -#endif - -#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5 -#define ARM_HAS_BX -#endif - -#ifdef ARM_HAS_BX -#define JMP(r) bx r -#else -#define JMP(r) mov pc, r -#endif -#endif /* __arm__ */ - -#endif /* UNWIND_ASSEMBLY_H */ Property changes on: head/contrib/llvm/projects/libunwind/src/assembly.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/Unwind-EHABI.h =================================================================== --- head/contrib/llvm/projects/libunwind/src/Unwind-EHABI.h (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/Unwind-EHABI.h (nonexistent) @@ -1,51 +0,0 @@ -//===------------------------- Unwind-EHABI.hpp ---------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -//===----------------------------------------------------------------------===// - -#ifndef __UNWIND_EHABI_H__ -#define __UNWIND_EHABI_H__ - -#include <__libunwind_config.h> - -#if defined(_LIBUNWIND_ARM_EHABI) - -#include -#include - -// Unable to unwind in the ARM index table (section 5 EHABI). -#define UNW_EXIDX_CANTUNWIND 0x1 - -static inline uint32_t signExtendPrel31(uint32_t data) { - return data | ((data & 0x40000000u) << 1); -} - -static inline uint32_t readPrel31(const uint32_t *data) { - return (((uint32_t)(uintptr_t)data) + signExtendPrel31(*data)); -} - -#if defined(__cplusplus) -extern "C" { -#endif - -extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr0( - _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); - -extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr1( - _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); - -extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr2( - _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context); - -#if defined(__cplusplus) -} // extern "C" -#endif - -#endif // defined(_LIBUNWIND_ARM_EHABI) - -#endif // __UNWIND_EHABI_H__ Property changes on: head/contrib/llvm/projects/libunwind/src/Unwind-EHABI.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/Unwind-sjlj.c =================================================================== --- head/contrib/llvm/projects/libunwind/src/Unwind-sjlj.c (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/Unwind-sjlj.c (nonexistent) @@ -1,504 +0,0 @@ -//===--------------------------- Unwind-sjlj.c ----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Implements setjump-longjump based C++ exceptions -// -//===----------------------------------------------------------------------===// - -#include - -#include -#include -#include - -#include "config.h" - -/// With SJLJ based exceptions, any function that has a catch clause or needs to -/// do any clean up when an exception propagates through it, needs to call -/// \c _Unwind_SjLj_Register at the start of the function and -/// \c _Unwind_SjLj_Unregister at the end. The register function is called with -/// the address of a block of memory in the function's stack frame. The runtime -/// keeps a linked list (stack) of these blocks - one per thread. The calling -/// function also sets the personality and lsda fields of the block. - -#if defined(_LIBUNWIND_BUILD_SJLJ_APIS) - -struct _Unwind_FunctionContext { - // next function in stack of handlers - struct _Unwind_FunctionContext *prev; - - // set by calling function before registering to be the landing pad - uint32_t resumeLocation; - - // set by personality handler to be parameters passed to landing pad function - uint32_t resumeParameters[4]; - - // set by calling function before registering - __personality_routine personality; // arm offset=24 - uintptr_t lsda; // arm offset=28 - - // variable length array, contains registers to restore - // 0 = r7, 1 = pc, 2 = sp - void *jbuf[]; -}; - -#if defined(_LIBUNWIND_HAS_NO_THREADS) -# define _LIBUNWIND_THREAD_LOCAL -#else -# if __STDC_VERSION__ >= 201112L -# define _LIBUNWIND_THREAD_LOCAL _Thread_local -# elif defined(_WIN32) -# define _LIBUNWIND_THREAD_LOCAL __declspec(thread) -# elif defined(__GNUC__) || defined(__clang__) -# define _LIBUNWIND_THREAD_LOCAL __thread -# else -# error Unable to create thread local storage -# endif -#endif - - -#if !defined(FOR_DYLD) - -#if defined(__APPLE__) -#include -#else -static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL; -#endif - -static struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() { -#if defined(__APPLE__) - return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key); -#else - return stack; -#endif -} - -static void -__Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc) { -#if defined(__APPLE__) - _pthread_setspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key, fc); -#else - stack = fc; -#endif -} - -#endif - - -/// Called at start of each function that catches exceptions -_LIBUNWIND_EXPORT void -_Unwind_SjLj_Register(struct _Unwind_FunctionContext *fc) { - fc->prev = __Unwind_SjLj_GetTopOfFunctionStack(); - __Unwind_SjLj_SetTopOfFunctionStack(fc); -} - - -/// Called at end of each function that catches exceptions -_LIBUNWIND_EXPORT void -_Unwind_SjLj_Unregister(struct _Unwind_FunctionContext *fc) { - __Unwind_SjLj_SetTopOfFunctionStack(fc->prev); -} - - -static _Unwind_Reason_Code -unwind_phase1(struct _Unwind_Exception *exception_object) { - _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p", c); - - // walk each frame looking for a place to stop - for (bool handlerNotFound = true; handlerNotFound; c = c->prev) { - - // check for no more frames - if (c == NULL) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): reached " - "bottom => _URC_END_OF_STACK", - exception_object); - return _URC_END_OF_STACK; - } - - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", c); - // if there is a personality routine, ask it if it will want to stop at this - // frame - if (c->personality != NULL) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): calling " - "personality function %p", - exception_object, c->personality); - _Unwind_Reason_Code personalityResult = (*c->personality)( - 1, _UA_SEARCH_PHASE, exception_object->exception_class, - exception_object, (struct _Unwind_Context *)c); - switch (personalityResult) { - case _URC_HANDLER_FOUND: - // found a catch clause or locals that need destructing in this frame - // stop search and remember function context - handlerNotFound = false; - exception_object->private_2 = (uintptr_t) c; - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): " - "_URC_HANDLER_FOUND", exception_object); - return _URC_NO_REASON; - - case _URC_CONTINUE_UNWIND: - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): " - "_URC_CONTINUE_UNWIND", exception_object); - // continue unwinding - break; - - default: - // something went wrong - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR", - exception_object); - return _URC_FATAL_PHASE1_ERROR; - } - } - } - return _URC_NO_REASON; -} - - -static _Unwind_Reason_Code -unwind_phase2(struct _Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", exception_object); - - // walk each frame until we reach where search phase said to stop - _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); - while (true) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2s(ex_ojb=%p): context=%p", - exception_object, c); - - // check for no more frames - if (c == NULL) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached " - "bottom => _URC_END_OF_STACK", - exception_object); - return _URC_END_OF_STACK; - } - - // if there is a personality routine, tell it we are unwinding - if (c->personality != NULL) { - _Unwind_Action action = _UA_CLEANUP_PHASE; - if ((uintptr_t) c == exception_object->private_2) - action = (_Unwind_Action)( - _UA_CLEANUP_PHASE | - _UA_HANDLER_FRAME); // tell personality this was the frame it marked - // in phase 1 - _Unwind_Reason_Code personalityResult = - (*c->personality)(1, action, exception_object->exception_class, - exception_object, (struct _Unwind_Context *)c); - switch (personalityResult) { - case _URC_CONTINUE_UNWIND: - // continue unwinding - _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND", - exception_object); - if ((uintptr_t) c == exception_object->private_2) { - // phase 1 said we would stop at this frame, but we did not... - _LIBUNWIND_ABORT("during phase1 personality function said it would " - "stop here, but now if phase2 it did not stop here"); - } - break; - case _URC_INSTALL_CONTEXT: - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): " - "_URC_INSTALL_CONTEXT, will resume at " - "landing pad %p", - exception_object, c->jbuf[1]); - // personality routine says to transfer control to landing pad - // we may get control back if landing pad calls _Unwind_Resume() - __Unwind_SjLj_SetTopOfFunctionStack(c); - __builtin_longjmp(c->jbuf, 1); - // unw_resume() only returns if there was an error - return _URC_FATAL_PHASE2_ERROR; - default: - // something went wrong - _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", - personalityResult); - return _URC_FATAL_PHASE2_ERROR; - } - } - c = c->prev; - } - - // clean up phase did not resume at the frame that the search phase said it - // would - return _URC_FATAL_PHASE2_ERROR; -} - - -static _Unwind_Reason_Code -unwind_phase2_forced(struct _Unwind_Exception *exception_object, - _Unwind_Stop_Fn stop, void *stop_parameter) { - // walk each frame until we reach where search phase said to stop - _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); - while (true) { - - // get next frame (skip over first which is _Unwind_RaiseException) - if (c == NULL) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached " - "bottom => _URC_END_OF_STACK", - exception_object); - return _URC_END_OF_STACK; - } - - // call stop function at each frame - _Unwind_Action action = - (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); - _Unwind_Reason_Code stopResult = - (*stop)(1, action, exception_object->exception_class, exception_object, - (struct _Unwind_Context *)c, stop_parameter); - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "stop function returned %d", - exception_object, stopResult); - if (stopResult != _URC_NO_REASON) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "stopped by stop function", - exception_object); - return _URC_FATAL_PHASE2_ERROR; - } - - // if there is a personality routine, tell it we are unwinding - if (c->personality != NULL) { - __personality_routine p = (__personality_routine) c->personality; - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "calling personality function %p", - exception_object, p); - _Unwind_Reason_Code personalityResult = - (*p)(1, action, exception_object->exception_class, exception_object, - (struct _Unwind_Context *)c); - switch (personalityResult) { - case _URC_CONTINUE_UNWIND: - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "personality returned _URC_CONTINUE_UNWIND", - exception_object); - // destructors called, continue unwinding - break; - case _URC_INSTALL_CONTEXT: - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "personality returned _URC_INSTALL_CONTEXT", - exception_object); - // we may get control back if landing pad calls _Unwind_Resume() - __Unwind_SjLj_SetTopOfFunctionStack(c); - __builtin_longjmp(c->jbuf, 1); - break; - default: - // something went wrong - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "personality returned %d, " - "_URC_FATAL_PHASE2_ERROR", - exception_object, personalityResult); - return _URC_FATAL_PHASE2_ERROR; - } - } - c = c->prev; - } - - // call stop function one last time and tell it we've reached the end of the - // stack - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " - "function with _UA_END_OF_STACK", - exception_object); - _Unwind_Action lastAction = - (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); - (*stop)(1, lastAction, exception_object->exception_class, exception_object, - (struct _Unwind_Context *)c, stop_parameter); - - // clean up phase did not resume at the frame that the search phase said it - // would - return _URC_FATAL_PHASE2_ERROR; -} - - -/// Called by __cxa_throw. Only returns if there is a fatal error -_LIBUNWIND_EXPORT _Unwind_Reason_Code -_Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)", exception_object); - - // mark that this is a non-forced unwind, so _Unwind_Resume() can do the right - // thing - exception_object->private_1 = 0; - exception_object->private_2 = 0; - - // phase 1: the search phase - _Unwind_Reason_Code phase1 = unwind_phase1(exception_object); - if (phase1 != _URC_NO_REASON) - return phase1; - - // phase 2: the clean up phase - return unwind_phase2(exception_object); -} - - - -/// When _Unwind_RaiseException() is in phase2, it hands control -/// to the personality function at each frame. The personality -/// may force a jump to a landing pad in that function, the landing -/// pad code may then call _Unwind_Resume() to continue with the -/// unwinding. Note: the call to _Unwind_Resume() is from compiler -/// geneated user code. All other _Unwind_* routines are called -/// by the C++ runtime __cxa_* routines. -/// -/// Re-throwing an exception is implemented by having the code call -/// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow() -_LIBUNWIND_EXPORT void -_Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)", exception_object); - - if (exception_object->private_1 != 0) - unwind_phase2_forced(exception_object, - (_Unwind_Stop_Fn) exception_object->private_1, - (void *)exception_object->private_2); - else - unwind_phase2(exception_object); - - // clients assume _Unwind_Resume() does not return, so all we can do is abort. - _LIBUNWIND_ABORT("_Unwind_SjLj_Resume() can't return"); -} - - -/// Called by __cxa_rethrow(). -_LIBUNWIND_EXPORT _Unwind_Reason_Code -_Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), " - "private_1=%ld", - exception_object, exception_object->private_1); - // If this is non-forced and a stopping place was found, then this is a - // re-throw. - // Call _Unwind_RaiseException() as if this was a new exception. - if (exception_object->private_1 == 0) { - return _Unwind_SjLj_RaiseException(exception_object); - // should return if there is no catch clause, so that __cxa_rethrow can call - // std::terminate() - } - - // Call through to _Unwind_Resume() which distiguishes between forced and - // regular exceptions. - _Unwind_SjLj_Resume(exception_object); - _LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called " - "_Unwind_SjLj_Resume() which unexpectedly returned"); -} - - -/// Called by personality handler during phase 2 to get LSDA for current frame. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; - _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) " - "=> 0x%0lX", context, ufc->lsda); - return ufc->lsda; -} - - -/// Called by personality handler during phase 2 to get register values. -_LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, - int index) { - _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)", - context, index); - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; - return ufc->resumeParameters[index]; -} - - -/// Called by personality handler during phase 2 to alter register values. -_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, - uintptr_t new_value) { - _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)" - , context, index, new_value); - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; - ufc->resumeParameters[index] = new_value; -} - - -/// Called by personality handler during phase 2 to get instruction pointer. -_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; - _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%lX", context, - ufc->resumeLocation + 1); - return ufc->resumeLocation + 1; -} - - -/// Called by personality handler during phase 2 to get instruction pointer. -/// ipBefore is a boolean that says if IP is already adjusted to be the call -/// site address. Normally IP is the return address. -_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, - int *ipBefore) { - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; - *ipBefore = 0; - _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX", - context, ipBefore, ufc->resumeLocation + 1); - return ufc->resumeLocation + 1; -} - - -/// Called by personality handler during phase 2 to alter instruction pointer. -_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, - uintptr_t new_value) { - _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0lX)", - context, new_value); - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; - ufc->resumeLocation = new_value - 1; -} - - -/// Called by personality handler during phase 2 to find the start of the -/// function. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetRegionStart(struct _Unwind_Context *context) { - // Not supported or needed for sjlj based unwinding - (void)context; - _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)", context); - return 0; -} - - -/// Called by personality handler during phase 2 if a foreign exception -/// is caught. -_LIBUNWIND_EXPORT void -_Unwind_DeleteException(struct _Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)", - exception_object); - if (exception_object->exception_cleanup != NULL) - (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, - exception_object); -} - - - -/// Called by personality handler during phase 2 to get base address for data -/// relative encodings. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetDataRelBase(struct _Unwind_Context *context) { - // Not supported or needed for sjlj based unwinding - (void)context; - _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", context); - _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented"); -} - - -/// Called by personality handler during phase 2 to get base address for text -/// relative encodings. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetTextRelBase(struct _Unwind_Context *context) { - // Not supported or needed for sjlj based unwinding - (void)context; - _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", context); - _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented"); -} - - -/// Called by personality handler to get "Call Frame Area" for current frame. -_LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { - _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)", context); - if (context != NULL) { - _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; - // Setjmp/longjmp based exceptions don't have a true CFA. - // Instead, the SP in the jmpbuf is the closest approximation. - return (uintptr_t) ufc->jbuf[2]; - } - return 0; -} - -#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS) Property changes on: head/contrib/llvm/projects/libunwind/src/Unwind-sjlj.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/AddressSpace.hpp =================================================================== --- head/contrib/llvm/projects/libunwind/src/AddressSpace.hpp (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/AddressSpace.hpp (nonexistent) @@ -1,738 +0,0 @@ -//===------------------------- AddressSpace.hpp ---------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Abstracts accessing local vs remote address spaces. -// -//===----------------------------------------------------------------------===// - -#ifndef __ADDRESSSPACE_HPP__ -#define __ADDRESSSPACE_HPP__ - -#include -#include -#include -#include - -#ifndef _LIBUNWIND_USE_DLADDR - #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) - #define _LIBUNWIND_USE_DLADDR 1 - #else - #define _LIBUNWIND_USE_DLADDR 0 - #endif -#endif - -#if _LIBUNWIND_USE_DLADDR -#include -#endif - -#ifdef __APPLE__ -#include -namespace libunwind { - bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde); -} -#endif - -#include "libunwind.h" -#include "config.h" -#include "dwarf2.h" -#include "EHHeaderParser.hpp" -#include "Registers.hpp" - -#ifdef __APPLE__ - - struct dyld_unwind_sections - { - const struct mach_header* mh; - const void* dwarf_section; - uintptr_t dwarf_section_length; - const void* compact_unwind_section; - uintptr_t compact_unwind_section_length; - }; - #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \ - && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \ - || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) - // In 10.7.0 or later, libSystem.dylib implements this function. - extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *); - #else - // In 10.6.x and earlier, we need to implement this functionality. Note - // that this requires a newer version of libmacho (from cctools) than is - // present in libSystem on 10.6.x (for getsectiondata). - static inline bool _dyld_find_unwind_sections(void* addr, - dyld_unwind_sections* info) { - // Find mach-o image containing address. - Dl_info dlinfo; - if (!dladdr(addr, &dlinfo)) - return false; -#if __LP64__ - const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase; -#else - const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase; -#endif - - // Initialize the return struct - info->mh = (const struct mach_header *)mh; - info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length); - info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length); - - if (!info->dwarf_section) { - info->dwarf_section_length = 0; - } - - if (!info->compact_unwind_section) { - info->compact_unwind_section_length = 0; - } - - return true; - } - #endif - -#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) - -// When statically linked on bare-metal, the symbols for the EH table are looked -// up without going through the dynamic loader. - -// The following linker script may be used to produce the necessary sections and symbols. -// Unless the --eh-frame-hdr linker option is provided, the section is not generated -// and does not take space in the output file. -// -// .eh_frame : -// { -// __eh_frame_start = .; -// KEEP(*(.eh_frame)) -// __eh_frame_end = .; -// } -// -// .eh_frame_hdr : -// { -// KEEP(*(.eh_frame_hdr)) -// } -// -// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; -// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; - -extern char __eh_frame_start; -extern char __eh_frame_end; - -#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) -extern char __eh_frame_hdr_start; -extern char __eh_frame_hdr_end; -#endif - -#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) - -// When statically linked on bare-metal, the symbols for the EH table are looked -// up without going through the dynamic loader. -extern char __exidx_start; -extern char __exidx_end; - -#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - -// ELF-based systems may use dl_iterate_phdr() to access sections -// containing unwinding information. The ElfW() macro for pointer-size -// independent ELF header traversal is not provided by on some -// systems (e.g., FreeBSD). On these systems the data structures are -// just called Elf_XXX. Define ElfW() locally. -#ifndef _WIN32 -#include -#else -#include -#include -#endif -#if !defined(ElfW) -#define ElfW(type) Elf_##type -#endif - -#endif - -namespace libunwind { - -/// Used by findUnwindSections() to return info about needed sections. -struct UnwindInfoSections { -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \ - defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) - // No dso_base for SEH or ARM EHABI. - uintptr_t dso_base; -#endif -#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - uintptr_t dwarf_section; - uintptr_t dwarf_section_length; -#endif -#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) - uintptr_t dwarf_index_section; - uintptr_t dwarf_index_section_length; -#endif -#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) - uintptr_t compact_unwind_section; - uintptr_t compact_unwind_section_length; -#endif -#if defined(_LIBUNWIND_ARM_EHABI) - uintptr_t arm_section; - uintptr_t arm_section_length; -#endif -}; - - -/// LocalAddressSpace is used as a template parameter to UnwindCursor when -/// unwinding a thread in the same process. The wrappers compile away, -/// making local unwinds fast. -class _LIBUNWIND_HIDDEN LocalAddressSpace { -public: - typedef uintptr_t pint_t; - typedef intptr_t sint_t; - uint8_t get8(pint_t addr) { - uint8_t val; - memcpy(&val, (void *)addr, sizeof(val)); - return val; - } - uint16_t get16(pint_t addr) { - uint16_t val; - memcpy(&val, (void *)addr, sizeof(val)); - return val; - } - uint32_t get32(pint_t addr) { - uint32_t val; - memcpy(&val, (void *)addr, sizeof(val)); - return val; - } - uint64_t get64(pint_t addr) { - uint64_t val; - memcpy(&val, (void *)addr, sizeof(val)); - return val; - } - double getDouble(pint_t addr) { - double val; - memcpy(&val, (void *)addr, sizeof(val)); - return val; - } - v128 getVector(pint_t addr) { - v128 val; - memcpy(&val, (void *)addr, sizeof(val)); - return val; - } - uintptr_t getP(pint_t addr); - uint64_t getRegister(pint_t addr); - static uint64_t getULEB128(pint_t &addr, pint_t end); - static int64_t getSLEB128(pint_t &addr, pint_t end); - - pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, - pint_t datarelBase = 0); - bool findFunctionName(pint_t addr, char *buf, size_t bufLen, - unw_word_t *offset); - bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); - bool findOtherFDE(pint_t targetAddr, pint_t &fde); - - static LocalAddressSpace sThisAddressSpace; -}; - -inline uintptr_t LocalAddressSpace::getP(pint_t addr) { -#if __SIZEOF_POINTER__ == 8 - return get64(addr); -#else - return get32(addr); -#endif -} - -inline uint64_t LocalAddressSpace::getRegister(pint_t addr) { -#if __SIZEOF_POINTER__ == 8 || defined(__mips64) - return get64(addr); -#else - return get32(addr); -#endif -} - -/// Read a ULEB128 into a 64-bit word. -inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) { - const uint8_t *p = (uint8_t *)addr; - const uint8_t *pend = (uint8_t *)end; - uint64_t result = 0; - int bit = 0; - do { - uint64_t b; - - if (p == pend) - _LIBUNWIND_ABORT("truncated uleb128 expression"); - - b = *p & 0x7f; - - if (bit >= 64 || b << bit >> bit != b) { - _LIBUNWIND_ABORT("malformed uleb128 expression"); - } else { - result |= b << bit; - bit += 7; - } - } while (*p++ >= 0x80); - addr = (pint_t) p; - return result; -} - -/// Read a SLEB128 into a 64-bit word. -inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { - const uint8_t *p = (uint8_t *)addr; - const uint8_t *pend = (uint8_t *)end; - int64_t result = 0; - int bit = 0; - uint8_t byte; - do { - if (p == pend) - _LIBUNWIND_ABORT("truncated sleb128 expression"); - byte = *p++; - result |= ((byte & 0x7f) << bit); - bit += 7; - } while (byte & 0x80); - // sign extend negative numbers - if ((byte & 0x40) != 0) - result |= (-1ULL) << bit; - addr = (pint_t) p; - return result; -} - -inline LocalAddressSpace::pint_t -LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, - pint_t datarelBase) { - pint_t startAddr = addr; - const uint8_t *p = (uint8_t *)addr; - pint_t result; - - // first get value - switch (encoding & 0x0F) { - case DW_EH_PE_ptr: - result = getP(addr); - p += sizeof(pint_t); - addr = (pint_t) p; - break; - case DW_EH_PE_uleb128: - result = (pint_t)getULEB128(addr, end); - break; - case DW_EH_PE_udata2: - result = get16(addr); - p += 2; - addr = (pint_t) p; - break; - case DW_EH_PE_udata4: - result = get32(addr); - p += 4; - addr = (pint_t) p; - break; - case DW_EH_PE_udata8: - result = (pint_t)get64(addr); - p += 8; - addr = (pint_t) p; - break; - case DW_EH_PE_sleb128: - result = (pint_t)getSLEB128(addr, end); - break; - case DW_EH_PE_sdata2: - // Sign extend from signed 16-bit value. - result = (pint_t)(int16_t)get16(addr); - p += 2; - addr = (pint_t) p; - break; - case DW_EH_PE_sdata4: - // Sign extend from signed 32-bit value. - result = (pint_t)(int32_t)get32(addr); - p += 4; - addr = (pint_t) p; - break; - case DW_EH_PE_sdata8: - result = (pint_t)get64(addr); - p += 8; - addr = (pint_t) p; - break; - default: - _LIBUNWIND_ABORT("unknown pointer encoding"); - } - - // then add relative offset - switch (encoding & 0x70) { - case DW_EH_PE_absptr: - // do nothing - break; - case DW_EH_PE_pcrel: - result += startAddr; - break; - case DW_EH_PE_textrel: - _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported"); - break; - case DW_EH_PE_datarel: - // DW_EH_PE_datarel is only valid in a few places, so the parameter has a - // default value of 0, and we abort in the event that someone calls this - // function with a datarelBase of 0 and DW_EH_PE_datarel encoding. - if (datarelBase == 0) - _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0"); - result += datarelBase; - break; - case DW_EH_PE_funcrel: - _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported"); - break; - case DW_EH_PE_aligned: - _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported"); - break; - default: - _LIBUNWIND_ABORT("unknown pointer encoding"); - break; - } - - if (encoding & DW_EH_PE_indirect) - result = getP(result); - - return result; -} - -inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, - UnwindInfoSections &info) { -#ifdef __APPLE__ - dyld_unwind_sections dyldInfo; - if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { - info.dso_base = (uintptr_t)dyldInfo.mh; - #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section; - info.dwarf_section_length = dyldInfo.dwarf_section_length; - #endif - info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section; - info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length; - return true; - } -#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) - // Bare metal is statically linked, so no need to ask the dynamic loader - info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start); - info.dwarf_section = (uintptr_t)(&__eh_frame_start); - _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", - (void *)info.dwarf_section, (void *)info.dwarf_section_length); -#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) - info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start); - info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start); - _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p", - (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length); -#endif - if (info.dwarf_section_length) - return true; -#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) - // Bare metal is statically linked, so no need to ask the dynamic loader - info.arm_section = (uintptr_t)(&__exidx_start); - info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start); - _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", - (void *)info.arm_section, (void *)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)) { - 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_SUPPORT_SEH_UNWIND) && defined(_WIN32) - // Don't even bother, since Windows has functions that do all this stuff - // for us. - return true; -#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) && \ - (__ANDROID_API__ < 21) - int length = 0; - info.arm_section = - (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); - info.arm_section_length = (uintptr_t)length; - if (info.arm_section && info.arm_section_length) - return true; -#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - struct dl_iterate_cb_data { - LocalAddressSpace *addressSpace; - UnwindInfoSections *sects; - uintptr_t targetAddr; - }; - - dl_iterate_cb_data cb_data = {this, &info, targetAddr}; - int found = dl_iterate_phdr( - [](struct dl_phdr_info *pinfo, size_t, void *data) -> int { - auto cbdata = static_cast(data); - bool found_obj = false; - bool found_hdr = false; - - assert(cbdata); - assert(cbdata->sects); - - if (cbdata->targetAddr < pinfo->dlpi_addr) { - return false; - } - -#if !defined(Elf_Half) - typedef ElfW(Half) Elf_Half; -#endif -#if !defined(Elf_Phdr) - typedef ElfW(Phdr) Elf_Phdr; -#endif -#if !defined(Elf_Addr) && defined(__ANDROID__) - typedef ElfW(Addr) Elf_Addr; -#endif - - #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) - #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." - #endif - size_t object_length; -#if defined(__ANDROID__) - Elf_Addr image_base = - pinfo->dlpi_phnum - ? reinterpret_cast(pinfo->dlpi_phdr) - - reinterpret_cast(pinfo->dlpi_phdr) - ->p_offset - : 0; -#endif - - for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { - const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; - if (phdr->p_type == PT_LOAD) { - uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; -#if defined(__ANDROID__) - if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base) - begin = begin + image_base; -#endif - uintptr_t end = begin + phdr->p_memsz; - if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { - cbdata->sects->dso_base = begin; - object_length = phdr->p_memsz; - found_obj = true; - } - } else if (phdr->p_type == PT_GNU_EH_FRAME) { - EHHeaderParser::EHHeaderInfo hdrInfo; - uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr; -#if defined(__ANDROID__) - if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base) - eh_frame_hdr_start = eh_frame_hdr_start + image_base; -#endif - cbdata->sects->dwarf_index_section = eh_frame_hdr_start; - cbdata->sects->dwarf_index_section_length = phdr->p_memsz; - found_hdr = EHHeaderParser::decodeEHHdr( - *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, - hdrInfo); - if (found_hdr) - cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; - } - } - - if (found_obj && found_hdr) { - cbdata->sects->dwarf_section_length = object_length; - return true; - } else { - return false; - } - #else // defined(_LIBUNWIND_ARM_EHABI) - for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { - const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; - if (phdr->p_type == PT_LOAD) { - uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; - uintptr_t end = begin + phdr->p_memsz; - if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) - found_obj = true; - } else if (phdr->p_type == PT_ARM_EXIDX) { - uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr; - cbdata->sects->arm_section = exidx_start; - cbdata->sects->arm_section_length = phdr->p_memsz; - found_hdr = true; - } - } - return found_obj && found_hdr; - #endif - }, - &cb_data); - return static_cast(found); -#endif - - return false; -} - - -inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { -#ifdef __APPLE__ - return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde)); -#else - // TO DO: if OS has way to dynamically register FDEs, check that. - (void)targetAddr; - (void)fde; - return false; -#endif -} - -inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, - size_t bufLen, - unw_word_t *offset) { -#if _LIBUNWIND_USE_DLADDR - Dl_info dyldInfo; - if (dladdr((void *)addr, &dyldInfo)) { - if (dyldInfo.dli_sname != NULL) { - snprintf(buf, bufLen, "%s", dyldInfo.dli_sname); - *offset = (addr - (pint_t) dyldInfo.dli_saddr); - return true; - } - } -#endif - return false; -} - - - -#ifdef UNW_REMOTE - -/// RemoteAddressSpace is used as a template parameter to UnwindCursor when -/// unwinding a thread in the another process. The other process can be a -/// different endianness and a different pointer size which is handled by -/// the P template parameter. -template -class RemoteAddressSpace { -public: - RemoteAddressSpace(task_t task) : fTask(task) {} - - typedef typename P::uint_t pint_t; - - uint8_t get8(pint_t addr); - uint16_t get16(pint_t addr); - uint32_t get32(pint_t addr); - uint64_t get64(pint_t addr); - pint_t getP(pint_t addr); - uint64_t getRegister(pint_t addr); - uint64_t getULEB128(pint_t &addr, pint_t end); - int64_t getSLEB128(pint_t &addr, pint_t end); - pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, - pint_t datarelBase = 0); - bool findFunctionName(pint_t addr, char *buf, size_t bufLen, - unw_word_t *offset); - bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); - bool findOtherFDE(pint_t targetAddr, pint_t &fde); -private: - void *localCopy(pint_t addr); - - task_t fTask; -}; - -template uint8_t RemoteAddressSpace

::get8(pint_t addr) { - return *((uint8_t *)localCopy(addr)); -} - -template uint16_t RemoteAddressSpace

::get16(pint_t addr) { - return P::E::get16(*(uint16_t *)localCopy(addr)); -} - -template uint32_t RemoteAddressSpace

::get32(pint_t addr) { - return P::E::get32(*(uint32_t *)localCopy(addr)); -} - -template uint64_t RemoteAddressSpace

::get64(pint_t addr) { - return P::E::get64(*(uint64_t *)localCopy(addr)); -} - -template -typename P::uint_t RemoteAddressSpace

::getP(pint_t addr) { - return P::getP(*(uint64_t *)localCopy(addr)); -} - -template -typename P::uint_t OtherAddressSpace

::getRegister(pint_t addr) { - return P::getRegister(*(uint64_t *)localCopy(addr)); -} - -template -uint64_t OtherAddressSpace

::getULEB128(pint_t &addr, pint_t end) { - uintptr_t size = (end - addr); - LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); - LocalAddressSpace::pint_t sladdr = laddr; - uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size); - addr += (laddr - sladdr); - return result; -} - -template -int64_t RemoteAddressSpace

::getSLEB128(pint_t &addr, pint_t end) { - uintptr_t size = (end - addr); - LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); - LocalAddressSpace::pint_t sladdr = laddr; - uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size); - addr += (laddr - sladdr); - return result; -} - -template void *RemoteAddressSpace

::localCopy(pint_t addr) { - // FIX ME -} - -template -bool RemoteAddressSpace

::findFunctionName(pint_t addr, char *buf, - size_t bufLen, - unw_word_t *offset) { - // FIX ME -} - -/// unw_addr_space is the base class that abstract unw_addr_space_t type in -/// libunwind.h points to. -struct unw_addr_space { - cpu_type_t cpuType; - task_t taskPort; -}; - -/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points -/// to when examining -/// a 32-bit intel process. -struct unw_addr_space_i386 : public unw_addr_space { - unw_addr_space_i386(task_t task) : oas(task) {} - RemoteAddressSpace> oas; -}; - -/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t -/// points to when examining -/// a 64-bit intel process. -struct unw_addr_space_x86_64 : public unw_addr_space { - unw_addr_space_x86_64(task_t task) : oas(task) {} - RemoteAddressSpace> oas; -}; - -/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points -/// to when examining -/// a 32-bit PowerPC process. -struct unw_addr_space_ppc : public unw_addr_space { - unw_addr_space_ppc(task_t task) : oas(task) {} - RemoteAddressSpace> oas; -}; - -/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points -/// to when examining a 64-bit PowerPC process. -struct unw_addr_space_ppc64 : public unw_addr_space { - unw_addr_space_ppc64(task_t task) : oas(task) {} - RemoteAddressSpace> oas; -}; - -#endif // UNW_REMOTE - -} // namespace libunwind - -#endif // __ADDRESSSPACE_HPP__ Index: head/contrib/llvm/projects/libunwind/src/config.h =================================================================== --- head/contrib/llvm/projects/libunwind/src/config.h (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/config.h (nonexistent) @@ -1,184 +0,0 @@ -//===----------------------------- config.h -------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Defines macros used within libunwind project. -// -//===----------------------------------------------------------------------===// - - -#ifndef LIBUNWIND_CONFIG_H -#define LIBUNWIND_CONFIG_H - -#include -#include -#include -#include - -// Define static_assert() unless already defined by compiler. -#ifndef __has_feature - #define __has_feature(__x) 0 -#endif -#if !(__has_feature(cxx_static_assert)) && !defined(static_assert) - #define static_assert(__b, __m) \ - extern int compile_time_assert_failed[ ( __b ) ? 1 : -1 ] \ - __attribute__( ( unused ) ); -#endif - -// Platform specific configuration defines. -#ifdef __APPLE__ - #if defined(FOR_DYLD) - #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND - #else - #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND - #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 - #endif -#elif defined(_WIN32) - #ifdef __SEH__ - #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1 - #else - #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 - #endif -#else - #if defined(__ARM_DWARF_EH__) || !defined(__arm__) - #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 - #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 - #endif -#endif - -#if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS) - #define _LIBUNWIND_EXPORT - #define _LIBUNWIND_HIDDEN -#else - #if !defined(__ELF__) && !defined(__MACH__) - #define _LIBUNWIND_EXPORT __declspec(dllexport) - #define _LIBUNWIND_HIDDEN - #else - #define _LIBUNWIND_EXPORT __attribute__((visibility("default"))) - #define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden"))) - #endif -#endif - -#if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__) -#define _LIBUNWIND_BUILD_SJLJ_APIS -#endif - -#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) -#define _LIBUNWIND_SUPPORT_FRAME_APIS -#endif - -#if defined(__i386__) || defined(__x86_64__) || \ - defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \ - (!defined(__APPLE__) && defined(__arm__)) || \ - (defined(__arm64__) || defined(__aarch64__)) || \ - defined(__mips__) || \ - defined(__riscv) -#if !defined(_LIBUNWIND_BUILD_SJLJ_APIS) -#define _LIBUNWIND_BUILD_ZERO_COST_APIS -#endif -#endif - -#if defined(__powerpc64__) && defined(_ARCH_PWR8) -#define PPC64_HAS_VMX -#endif - -#if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL) -#define _LIBUNWIND_ABORT(msg) \ - do { \ - abort(); \ - } while (0) -#else -#define _LIBUNWIND_ABORT(msg) \ - do { \ - fprintf(stderr, "libunwind: %s %s:%d - %s\n", __func__, __FILE__, \ - __LINE__, msg); \ - fflush(stderr); \ - abort(); \ - } while (0) -#endif - -#if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL) -#define _LIBUNWIND_LOG0(msg) -#define _LIBUNWIND_LOG(msg, ...) -#else -#define _LIBUNWIND_LOG0(msg) \ - fprintf(stderr, "libunwind: " msg "\n") -#define _LIBUNWIND_LOG(msg, ...) \ - fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__) -#endif - -#if defined(NDEBUG) - #define _LIBUNWIND_LOG_IF_FALSE(x) x -#else - #define _LIBUNWIND_LOG_IF_FALSE(x) \ - do { \ - bool _ret = x; \ - if (!_ret) \ - _LIBUNWIND_LOG("" #x " failed in %s", __FUNCTION__); \ - } while (0) -#endif - -// Macros that define away in non-Debug builds -#ifdef NDEBUG - #define _LIBUNWIND_DEBUG_LOG(msg, ...) - #define _LIBUNWIND_TRACE_API(msg, ...) - #define _LIBUNWIND_TRACING_UNWINDING (0) - #define _LIBUNWIND_TRACING_DWARF (0) - #define _LIBUNWIND_TRACE_UNWINDING(msg, ...) - #define _LIBUNWIND_TRACE_DWARF(...) -#else - #ifdef __cplusplus - extern "C" { - #endif - extern bool logAPIs(); - extern bool logUnwinding(); - extern bool logDWARF(); - #ifdef __cplusplus - } - #endif - #define _LIBUNWIND_DEBUG_LOG(msg, ...) _LIBUNWIND_LOG(msg, __VA_ARGS__) - #define _LIBUNWIND_TRACE_API(msg, ...) \ - do { \ - if (logAPIs()) \ - _LIBUNWIND_LOG(msg, __VA_ARGS__); \ - } while (0) - #define _LIBUNWIND_TRACING_UNWINDING logUnwinding() - #define _LIBUNWIND_TRACING_DWARF logDWARF() - #define _LIBUNWIND_TRACE_UNWINDING(msg, ...) \ - do { \ - if (logUnwinding()) \ - _LIBUNWIND_LOG(msg, __VA_ARGS__); \ - } while (0) - #define _LIBUNWIND_TRACE_DWARF(...) \ - do { \ - if (logDWARF()) \ - fprintf(stderr, __VA_ARGS__); \ - } while (0) -#endif - -#ifdef __cplusplus -// Used to fit UnwindCursor and Registers_xxx types against unw_context_t / -// unw_cursor_t sized memory blocks. -#if defined(_LIBUNWIND_IS_NATIVE_ONLY) -# define COMP_OP == -#else -# define COMP_OP <= -#endif -template -struct check_fit { - template - struct blk_count { - static const size_t count = - (sizeof(T) + sizeof(uint64_t) - 1) / sizeof(uint64_t); - }; - static const bool does_fit = - (blk_count<_Type>::count COMP_OP blk_count<_Mem>::count); -}; -#undef COMP_OP -#endif // __cplusplus - -#endif // LIBUNWIND_CONFIG_H Property changes on: head/contrib/llvm/projects/libunwind/src/config.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/src/CompactUnwinder.hpp =================================================================== --- head/contrib/llvm/projects/libunwind/src/CompactUnwinder.hpp (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/CompactUnwinder.hpp (nonexistent) @@ -1,698 +0,0 @@ -//===-------------------------- CompactUnwinder.hpp -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Does runtime stack unwinding using compact unwind encodings. -// -//===----------------------------------------------------------------------===// - -#ifndef __COMPACT_UNWINDER_HPP__ -#define __COMPACT_UNWINDER_HPP__ - -#include -#include - -#include -#include - -#include "Registers.hpp" - -#define EXTRACT_BITS(value, mask) \ - ((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1)) - -namespace libunwind { - -#if defined(_LIBUNWIND_TARGET_I386) -/// CompactUnwinder_x86 uses a compact unwind info to virtually "step" (aka -/// unwind) by modifying a Registers_x86 register set -template -class CompactUnwinder_x86 { -public: - - static int stepWithCompactEncoding(compact_unwind_encoding_t info, - uint32_t functionStart, A &addressSpace, - Registers_x86 ®isters); - -private: - typename A::pint_t pint_t; - - static void frameUnwind(A &addressSpace, Registers_x86 ®isters); - static void framelessUnwind(A &addressSpace, - typename A::pint_t returnAddressLocation, - Registers_x86 ®isters); - static int - stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding, - uint32_t functionStart, A &addressSpace, - Registers_x86 ®isters); - static int stepWithCompactEncodingFrameless( - compact_unwind_encoding_t compactEncoding, uint32_t functionStart, - A &addressSpace, Registers_x86 ®isters, bool indirectStackSize); -}; - -template -int CompactUnwinder_x86::stepWithCompactEncoding( - compact_unwind_encoding_t compactEncoding, uint32_t functionStart, - A &addressSpace, Registers_x86 ®isters) { - switch (compactEncoding & UNWIND_X86_MODE_MASK) { - case UNWIND_X86_MODE_EBP_FRAME: - return stepWithCompactEncodingEBPFrame(compactEncoding, functionStart, - addressSpace, registers); - case UNWIND_X86_MODE_STACK_IMMD: - return stepWithCompactEncodingFrameless(compactEncoding, functionStart, - addressSpace, registers, false); - case UNWIND_X86_MODE_STACK_IND: - return stepWithCompactEncodingFrameless(compactEncoding, functionStart, - addressSpace, registers, true); - } - _LIBUNWIND_ABORT("invalid compact unwind encoding"); -} - -template -int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( - compact_unwind_encoding_t compactEncoding, uint32_t functionStart, - A &addressSpace, Registers_x86 ®isters) { - uint32_t savedRegistersOffset = - EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_OFFSET); - uint32_t savedRegistersLocations = - EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_REGISTERS); - - uint32_t savedRegisters = registers.getEBP() - 4 * savedRegistersOffset; - for (int i = 0; i < 5; ++i) { - switch (savedRegistersLocations & 0x7) { - case UNWIND_X86_REG_NONE: - // no register saved in this slot - break; - case UNWIND_X86_REG_EBX: - registers.setEBX(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_ECX: - registers.setECX(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_EDX: - registers.setEDX(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_EDI: - registers.setEDI(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_ESI: - registers.setESI(addressSpace.get32(savedRegisters)); - break; - default: - (void)functionStart; - _LIBUNWIND_DEBUG_LOG("bad register for EBP frame, encoding=%08X for " - "function starting at 0x%X", - compactEncoding, functionStart); - _LIBUNWIND_ABORT("invalid compact unwind encoding"); - } - savedRegisters += 4; - savedRegistersLocations = (savedRegistersLocations >> 3); - } - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; -} - -template -int CompactUnwinder_x86::stepWithCompactEncodingFrameless( - compact_unwind_encoding_t encoding, uint32_t functionStart, - A &addressSpace, Registers_x86 ®isters, bool indirectStackSize) { - uint32_t stackSizeEncoded = - EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); - uint32_t stackAdjust = - EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST); - uint32_t regCount = - EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); - uint32_t permutation = - EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); - uint32_t stackSize = stackSizeEncoded * 4; - if (indirectStackSize) { - // stack size is encoded in subl $xxx,%esp instruction - uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded); - stackSize = subl + 4 * stackAdjust; - } - // decompress permutation - uint32_t permunreg[6]; - switch (regCount) { - case 6: - permunreg[0] = permutation / 120; - permutation -= (permunreg[0] * 120); - permunreg[1] = permutation / 24; - permutation -= (permunreg[1] * 24); - permunreg[2] = permutation / 6; - permutation -= (permunreg[2] * 6); - permunreg[3] = permutation / 2; - permutation -= (permunreg[3] * 2); - permunreg[4] = permutation; - permunreg[5] = 0; - break; - case 5: - permunreg[0] = permutation / 120; - permutation -= (permunreg[0] * 120); - permunreg[1] = permutation / 24; - permutation -= (permunreg[1] * 24); - permunreg[2] = permutation / 6; - permutation -= (permunreg[2] * 6); - permunreg[3] = permutation / 2; - permutation -= (permunreg[3] * 2); - permunreg[4] = permutation; - break; - case 4: - permunreg[0] = permutation / 60; - permutation -= (permunreg[0] * 60); - permunreg[1] = permutation / 12; - permutation -= (permunreg[1] * 12); - permunreg[2] = permutation / 3; - permutation -= (permunreg[2] * 3); - permunreg[3] = permutation; - break; - case 3: - permunreg[0] = permutation / 20; - permutation -= (permunreg[0] * 20); - permunreg[1] = permutation / 4; - permutation -= (permunreg[1] * 4); - permunreg[2] = permutation; - break; - case 2: - permunreg[0] = permutation / 5; - permutation -= (permunreg[0] * 5); - permunreg[1] = permutation; - break; - case 1: - permunreg[0] = permutation; - break; - } - // re-number registers back to standard numbers - int registersSaved[6]; - bool used[7] = { false, false, false, false, false, false, false }; - for (uint32_t i = 0; i < regCount; ++i) { - uint32_t renum = 0; - for (int u = 1; u < 7; ++u) { - if (!used[u]) { - if (renum == permunreg[i]) { - registersSaved[i] = u; - used[u] = true; - break; - } - ++renum; - } - } - } - uint32_t savedRegisters = registers.getSP() + stackSize - 4 - 4 * regCount; - for (uint32_t i = 0; i < regCount; ++i) { - switch (registersSaved[i]) { - case UNWIND_X86_REG_EBX: - registers.setEBX(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_ECX: - registers.setECX(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_EDX: - registers.setEDX(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_EDI: - registers.setEDI(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_ESI: - registers.setESI(addressSpace.get32(savedRegisters)); - break; - case UNWIND_X86_REG_EBP: - registers.setEBP(addressSpace.get32(savedRegisters)); - break; - default: - _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " - "function starting at 0x%X", - encoding, functionStart); - _LIBUNWIND_ABORT("invalid compact unwind encoding"); - } - savedRegisters += 4; - } - framelessUnwind(addressSpace, savedRegisters, registers); - return UNW_STEP_SUCCESS; -} - - -template -void CompactUnwinder_x86::frameUnwind(A &addressSpace, - Registers_x86 ®isters) { - typename A::pint_t bp = registers.getEBP(); - // ebp points to old ebp - registers.setEBP(addressSpace.get32(bp)); - // old esp is ebp less saved ebp and return address - registers.setSP((uint32_t)bp + 8); - // pop return address into eip - registers.setIP(addressSpace.get32(bp + 4)); -} - -template -void CompactUnwinder_x86::framelessUnwind( - A &addressSpace, typename A::pint_t returnAddressLocation, - Registers_x86 ®isters) { - // return address is on stack after last saved register - registers.setIP(addressSpace.get32(returnAddressLocation)); - // old esp is before return address - registers.setSP((uint32_t)returnAddressLocation + 4); -} -#endif // _LIBUNWIND_TARGET_I386 - - -#if defined(_LIBUNWIND_TARGET_X86_64) -/// CompactUnwinder_x86_64 uses a compact unwind info to virtually "step" (aka -/// unwind) by modifying a Registers_x86_64 register set -template -class CompactUnwinder_x86_64 { -public: - - static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, - uint64_t functionStart, A &addressSpace, - Registers_x86_64 ®isters); - -private: - typename A::pint_t pint_t; - - static void frameUnwind(A &addressSpace, Registers_x86_64 ®isters); - static void framelessUnwind(A &addressSpace, uint64_t returnAddressLocation, - Registers_x86_64 ®isters); - static int - stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding, - uint64_t functionStart, A &addressSpace, - Registers_x86_64 ®isters); - static int stepWithCompactEncodingFrameless( - compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_x86_64 ®isters, bool indirectStackSize); -}; - -template -int CompactUnwinder_x86_64::stepWithCompactEncoding( - compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_x86_64 ®isters) { - switch (compactEncoding & UNWIND_X86_64_MODE_MASK) { - case UNWIND_X86_64_MODE_RBP_FRAME: - return stepWithCompactEncodingRBPFrame(compactEncoding, functionStart, - addressSpace, registers); - case UNWIND_X86_64_MODE_STACK_IMMD: - return stepWithCompactEncodingFrameless(compactEncoding, functionStart, - addressSpace, registers, false); - case UNWIND_X86_64_MODE_STACK_IND: - return stepWithCompactEncodingFrameless(compactEncoding, functionStart, - addressSpace, registers, true); - } - _LIBUNWIND_ABORT("invalid compact unwind encoding"); -} - -template -int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( - compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_x86_64 ®isters) { - uint32_t savedRegistersOffset = - EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_OFFSET); - uint32_t savedRegistersLocations = - EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); - - uint64_t savedRegisters = registers.getRBP() - 8 * savedRegistersOffset; - for (int i = 0; i < 5; ++i) { - switch (savedRegistersLocations & 0x7) { - case UNWIND_X86_64_REG_NONE: - // no register saved in this slot - break; - case UNWIND_X86_64_REG_RBX: - registers.setRBX(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_R12: - registers.setR12(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_R13: - registers.setR13(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_R14: - registers.setR14(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_R15: - registers.setR15(addressSpace.get64(savedRegisters)); - break; - default: - (void)functionStart; - _LIBUNWIND_DEBUG_LOG("bad register for RBP frame, encoding=%08X for " - "function starting at 0x%llX", - compactEncoding, functionStart); - _LIBUNWIND_ABORT("invalid compact unwind encoding"); - } - savedRegisters += 8; - savedRegistersLocations = (savedRegistersLocations >> 3); - } - frameUnwind(addressSpace, registers); - return UNW_STEP_SUCCESS; -} - -template -int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( - compact_unwind_encoding_t encoding, uint64_t functionStart, A &addressSpace, - Registers_x86_64 ®isters, bool indirectStackSize) { - uint32_t stackSizeEncoded = - EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); - uint32_t stackAdjust = - EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); - uint32_t regCount = - EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); - uint32_t permutation = - EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); - uint32_t stackSize = stackSizeEncoded * 8; - if (indirectStackSize) { - // stack size is encoded in subl $xxx,%esp instruction - uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded); - stackSize = subl + 8 * stackAdjust; - } - // decompress permutation - uint32_t permunreg[6]; - switch (regCount) { - case 6: - permunreg[0] = permutation / 120; - permutation -= (permunreg[0] * 120); - permunreg[1] = permutation / 24; - permutation -= (permunreg[1] * 24); - permunreg[2] = permutation / 6; - permutation -= (permunreg[2] * 6); - permunreg[3] = permutation / 2; - permutation -= (permunreg[3] * 2); - permunreg[4] = permutation; - permunreg[5] = 0; - break; - case 5: - permunreg[0] = permutation / 120; - permutation -= (permunreg[0] * 120); - permunreg[1] = permutation / 24; - permutation -= (permunreg[1] * 24); - permunreg[2] = permutation / 6; - permutation -= (permunreg[2] * 6); - permunreg[3] = permutation / 2; - permutation -= (permunreg[3] * 2); - permunreg[4] = permutation; - break; - case 4: - permunreg[0] = permutation / 60; - permutation -= (permunreg[0] * 60); - permunreg[1] = permutation / 12; - permutation -= (permunreg[1] * 12); - permunreg[2] = permutation / 3; - permutation -= (permunreg[2] * 3); - permunreg[3] = permutation; - break; - case 3: - permunreg[0] = permutation / 20; - permutation -= (permunreg[0] * 20); - permunreg[1] = permutation / 4; - permutation -= (permunreg[1] * 4); - permunreg[2] = permutation; - break; - case 2: - permunreg[0] = permutation / 5; - permutation -= (permunreg[0] * 5); - permunreg[1] = permutation; - break; - case 1: - permunreg[0] = permutation; - break; - } - // re-number registers back to standard numbers - int registersSaved[6]; - bool used[7] = { false, false, false, false, false, false, false }; - for (uint32_t i = 0; i < regCount; ++i) { - uint32_t renum = 0; - for (int u = 1; u < 7; ++u) { - if (!used[u]) { - if (renum == permunreg[i]) { - registersSaved[i] = u; - used[u] = true; - break; - } - ++renum; - } - } - } - uint64_t savedRegisters = registers.getSP() + stackSize - 8 - 8 * regCount; - for (uint32_t i = 0; i < regCount; ++i) { - switch (registersSaved[i]) { - case UNWIND_X86_64_REG_RBX: - registers.setRBX(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_R12: - registers.setR12(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_R13: - registers.setR13(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_R14: - registers.setR14(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_R15: - registers.setR15(addressSpace.get64(savedRegisters)); - break; - case UNWIND_X86_64_REG_RBP: - registers.setRBP(addressSpace.get64(savedRegisters)); - break; - default: - _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " - "function starting at 0x%llX", - encoding, functionStart); - _LIBUNWIND_ABORT("invalid compact unwind encoding"); - } - savedRegisters += 8; - } - framelessUnwind(addressSpace, savedRegisters, registers); - return UNW_STEP_SUCCESS; -} - - -template -void CompactUnwinder_x86_64::frameUnwind(A &addressSpace, - Registers_x86_64 ®isters) { - uint64_t rbp = registers.getRBP(); - // ebp points to old ebp - registers.setRBP(addressSpace.get64(rbp)); - // old esp is ebp less saved ebp and return address - registers.setSP(rbp + 16); - // pop return address into eip - registers.setIP(addressSpace.get64(rbp + 8)); -} - -template -void CompactUnwinder_x86_64::framelessUnwind(A &addressSpace, - uint64_t returnAddressLocation, - Registers_x86_64 ®isters) { - // return address is on stack after last saved register - registers.setIP(addressSpace.get64(returnAddressLocation)); - // old esp is before return address - registers.setSP(returnAddressLocation + 8); -} -#endif // _LIBUNWIND_TARGET_X86_64 - - - -#if defined(_LIBUNWIND_TARGET_AARCH64) -/// CompactUnwinder_arm64 uses a compact unwind info to virtually "step" (aka -/// unwind) by modifying a Registers_arm64 register set -template -class CompactUnwinder_arm64 { -public: - - static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, - uint64_t functionStart, A &addressSpace, - Registers_arm64 ®isters); - -private: - typename A::pint_t pint_t; - - static int - stepWithCompactEncodingFrame(compact_unwind_encoding_t compactEncoding, - uint64_t functionStart, A &addressSpace, - Registers_arm64 ®isters); - static int stepWithCompactEncodingFrameless( - compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_arm64 ®isters); -}; - -template -int CompactUnwinder_arm64::stepWithCompactEncoding( - compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_arm64 ®isters) { - switch (compactEncoding & UNWIND_ARM64_MODE_MASK) { - case UNWIND_ARM64_MODE_FRAME: - return stepWithCompactEncodingFrame(compactEncoding, functionStart, - addressSpace, registers); - case UNWIND_ARM64_MODE_FRAMELESS: - return stepWithCompactEncodingFrameless(compactEncoding, functionStart, - addressSpace, registers); - } - _LIBUNWIND_ABORT("invalid compact unwind encoding"); -} - -template -int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( - compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, - Registers_arm64 ®isters) { - uint32_t stackSize = - 16 * EXTRACT_BITS(encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK); - - uint64_t savedRegisterLoc = registers.getSP() + stackSize; - - if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { - registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - - if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { - registers.setFloatRegister(UNW_ARM64_D8, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D9, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { - registers.setFloatRegister(UNW_ARM64_D10, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D11, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { - registers.setFloatRegister(UNW_ARM64_D12, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D13, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { - registers.setFloatRegister(UNW_ARM64_D14, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D15, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - - // subtract stack size off of sp - registers.setSP(savedRegisterLoc); - - // set pc to be value in lr - registers.setIP(registers.getRegister(UNW_ARM64_LR)); - - return UNW_STEP_SUCCESS; -} - -template -int CompactUnwinder_arm64::stepWithCompactEncodingFrame( - compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, - Registers_arm64 ®isters) { - uint64_t savedRegisterLoc = registers.getFP() - 8; - - if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { - registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - - if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { - registers.setFloatRegister(UNW_ARM64_D8, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D9, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { - registers.setFloatRegister(UNW_ARM64_D10, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D11, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { - registers.setFloatRegister(UNW_ARM64_D12, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D13, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { - registers.setFloatRegister(UNW_ARM64_D14, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D15, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - - uint64_t fp = registers.getFP(); - // fp points to old fp - registers.setFP(addressSpace.get64(fp)); - // old sp is fp less saved fp and lr - registers.setSP(fp + 16); - // pop return address into pc - registers.setIP(addressSpace.get64(fp + 8)); - - return UNW_STEP_SUCCESS; -} -#endif // _LIBUNWIND_TARGET_AARCH64 - - -} // namespace libunwind - -#endif // __COMPACT_UNWINDER_HPP__ Index: head/contrib/llvm/projects/libunwind/src/DwarfParser.hpp =================================================================== --- head/contrib/llvm/projects/libunwind/src/DwarfParser.hpp (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/DwarfParser.hpp (nonexistent) @@ -1,766 +0,0 @@ -//===--------------------------- DwarfParser.hpp --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Parses DWARF CFIs (FDEs and CIEs). -// -//===----------------------------------------------------------------------===// - -#ifndef __DWARF_PARSER_HPP__ -#define __DWARF_PARSER_HPP__ - -#include -#include -#include -#include - -#include "libunwind.h" -#include "dwarf2.h" -#include "Registers.hpp" - -#include "config.h" - -namespace libunwind { - -/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records. -/// See DWARF Spec for details: -/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html -/// -template -class CFI_Parser { -public: - typedef typename A::pint_t pint_t; - - /// Information encoded in a CIE (Common Information Entry) - struct CIE_Info { - pint_t cieStart; - pint_t cieLength; - pint_t cieInstructions; - uint8_t pointerEncoding; - uint8_t lsdaEncoding; - uint8_t personalityEncoding; - uint8_t personalityOffsetInCIE; - pint_t personality; - uint32_t codeAlignFactor; - int dataAlignFactor; - bool isSignalFrame; - bool fdesHaveAugmentationData; - uint8_t returnAddressRegister; -#if defined(_LIBUNWIND_TARGET_AARCH64) - bool addressesSignedWithBKey; -#endif - }; - - /// Information about an FDE (Frame Description Entry) - struct FDE_Info { - pint_t fdeStart; - pint_t fdeLength; - pint_t fdeInstructions; - pint_t pcStart; - pint_t pcEnd; - pint_t lsda; - }; - - enum { - kMaxRegisterNumber = _LIBUNWIND_HIGHEST_DWARF_REGISTER - }; - enum RegisterSavedWhere { - kRegisterUnused, - kRegisterInCFA, - kRegisterOffsetFromCFA, - kRegisterInRegister, - kRegisterAtExpression, - kRegisterIsExpression - }; - struct RegisterLocation { - RegisterSavedWhere location; - int64_t value; - }; - /// Information about a frame layout and registers saved determined - /// by "running" the DWARF FDE "instructions" - struct PrologInfo { - uint32_t cfaRegister; - int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset - int64_t cfaExpression; // CFA = expression - uint32_t spExtraArgSize; - uint32_t codeOffsetAtStackDecrement; - bool registersInOtherRegisters; - bool sameValueUsed; - RegisterLocation savedRegisters[kMaxRegisterNumber + 1]; - }; - - struct PrologInfoStackEntry { - PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i) - : next(n), info(i) {} - PrologInfoStackEntry *next; - PrologInfo info; - }; - - static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, - uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, - CIE_Info *cieInfo); - static const char *decodeFDE(A &addressSpace, pint_t fdeStart, - FDE_Info *fdeInfo, CIE_Info *cieInfo); - static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, - const CIE_Info &cieInfo, pint_t upToPC, - int arch, PrologInfo *results); - - static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); - -private: - static bool parseInstructions(A &addressSpace, pint_t instructions, - pint_t instructionsEnd, const CIE_Info &cieInfo, - pint_t pcoffset, - PrologInfoStackEntry *&rememberStack, int arch, - PrologInfo *results); -}; - -/// Parse a FDE into a CIE_Info and an FDE_Info -template -const char *CFI_Parser::decodeFDE(A &addressSpace, pint_t fdeStart, - FDE_Info *fdeInfo, CIE_Info *cieInfo) { - pint_t p = fdeStart; - pint_t cfiLength = (pint_t)addressSpace.get32(p); - p += 4; - if (cfiLength == 0xffffffff) { - // 0xffffffff means length is really next 8 bytes - cfiLength = (pint_t)addressSpace.get64(p); - p += 8; - } - if (cfiLength == 0) - return "FDE has zero length"; // end marker - uint32_t ciePointer = addressSpace.get32(p); - if (ciePointer == 0) - return "FDE is really a CIE"; // this is a CIE not an FDE - pint_t nextCFI = p + cfiLength; - pint_t cieStart = p - ciePointer; - const char *err = parseCIE(addressSpace, cieStart, cieInfo); - if (err != NULL) - return err; - p += 4; - // Parse pc begin and range. - pint_t pcStart = - addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding); - pint_t pcRange = - addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F); - // Parse rest of info. - fdeInfo->lsda = 0; - // Check for augmentation length. - if (cieInfo->fdesHaveAugmentationData) { - pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI); - pint_t endOfAug = p + augLen; - if (cieInfo->lsdaEncoding != DW_EH_PE_omit) { - // Peek at value (without indirection). Zero means no LSDA. - pint_t lsdaStart = p; - if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != - 0) { - // Reset pointer and re-parse LSDA address. - p = lsdaStart; - fdeInfo->lsda = - addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding); - } - } - p = endOfAug; - } - fdeInfo->fdeStart = fdeStart; - fdeInfo->fdeLength = nextCFI - fdeStart; - fdeInfo->fdeInstructions = p; - fdeInfo->pcStart = pcStart; - fdeInfo->pcEnd = pcStart + pcRange; - return NULL; // success -} - -/// Scan an eh_frame section to find an FDE for a pc -template -bool CFI_Parser::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, - uint32_t sectionLength, pint_t fdeHint, - FDE_Info *fdeInfo, CIE_Info *cieInfo) { - //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); - pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart; - const pint_t ehSectionEnd = p + sectionLength; - while (p < ehSectionEnd) { - pint_t currentCFI = p; - //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p); - pint_t cfiLength = addressSpace.get32(p); - p += 4; - if (cfiLength == 0xffffffff) { - // 0xffffffff means length is really next 8 bytes - cfiLength = (pint_t)addressSpace.get64(p); - p += 8; - } - if (cfiLength == 0) - return false; // end marker - uint32_t id = addressSpace.get32(p); - if (id == 0) { - // Skip over CIEs. - p += cfiLength; - } else { - // Process FDE to see if it covers pc. - pint_t nextCFI = p + cfiLength; - uint32_t ciePointer = addressSpace.get32(p); - pint_t cieStart = p - ciePointer; - // Validate pointer to CIE is within section. - if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) { - if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) { - p += 4; - // Parse pc begin and range. - pint_t pcStart = - addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding); - pint_t pcRange = addressSpace.getEncodedP( - p, nextCFI, cieInfo->pointerEncoding & 0x0F); - // Test if pc is within the function this FDE covers. - if ((pcStart < pc) && (pc <= pcStart + pcRange)) { - // parse rest of info - fdeInfo->lsda = 0; - // check for augmentation length - if (cieInfo->fdesHaveAugmentationData) { - pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI); - pint_t endOfAug = p + augLen; - if (cieInfo->lsdaEncoding != DW_EH_PE_omit) { - // Peek at value (without indirection). Zero means no LSDA. - pint_t lsdaStart = p; - if (addressSpace.getEncodedP( - p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) { - // Reset pointer and re-parse LSDA address. - p = lsdaStart; - fdeInfo->lsda = addressSpace - .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding); - } - } - p = endOfAug; - } - fdeInfo->fdeStart = currentCFI; - fdeInfo->fdeLength = nextCFI - currentCFI; - fdeInfo->fdeInstructions = p; - fdeInfo->pcStart = pcStart; - fdeInfo->pcEnd = pcStart + pcRange; - return true; - } else { - // pc is not in begin/range, skip this FDE - } - } else { - // Malformed CIE, now augmentation describing pc range encoding. - } - } else { - // malformed FDE. CIE is bad - } - p = nextCFI; - } - } - return false; -} - -/// Extract info from a CIE -template -const char *CFI_Parser::parseCIE(A &addressSpace, pint_t cie, - CIE_Info *cieInfo) { - cieInfo->pointerEncoding = 0; - cieInfo->lsdaEncoding = DW_EH_PE_omit; - cieInfo->personalityEncoding = 0; - cieInfo->personalityOffsetInCIE = 0; - cieInfo->personality = 0; - cieInfo->codeAlignFactor = 0; - cieInfo->dataAlignFactor = 0; - cieInfo->isSignalFrame = false; - cieInfo->fdesHaveAugmentationData = false; -#if defined(_LIBUNWIND_TARGET_AARCH64) - cieInfo->addressesSignedWithBKey = false; -#endif - cieInfo->cieStart = cie; - pint_t p = cie; - pint_t cieLength = (pint_t)addressSpace.get32(p); - p += 4; - pint_t cieContentEnd = p + cieLength; - if (cieLength == 0xffffffff) { - // 0xffffffff means length is really next 8 bytes - cieLength = (pint_t)addressSpace.get64(p); - p += 8; - cieContentEnd = p + cieLength; - } - if (cieLength == 0) - return NULL; - // CIE ID is always 0 - if (addressSpace.get32(p) != 0) - return "CIE ID is not zero"; - p += 4; - // Version is always 1 or 3 - uint8_t version = addressSpace.get8(p); - if ((version != 1) && (version != 3)) - return "CIE version is not 1 or 3"; - ++p; - // save start of augmentation string and find end - pint_t strStart = p; - while (addressSpace.get8(p) != 0) - ++p; - ++p; - // parse code aligment factor - cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd); - // parse data alignment factor - cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd); - // parse return address register - uint64_t raReg = addressSpace.getULEB128(p, cieContentEnd); - assert(raReg < 255 && "return address register too large"); - cieInfo->returnAddressRegister = (uint8_t)raReg; - // parse augmentation data based on augmentation string - const char *result = NULL; - if (addressSpace.get8(strStart) == 'z') { - // parse augmentation data length - addressSpace.getULEB128(p, cieContentEnd); - for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) { - switch (addressSpace.get8(s)) { - case 'z': - cieInfo->fdesHaveAugmentationData = true; - break; - case 'P': - cieInfo->personalityEncoding = addressSpace.get8(p); - ++p; - cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie); - cieInfo->personality = addressSpace - .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding); - break; - case 'L': - cieInfo->lsdaEncoding = addressSpace.get8(p); - ++p; - break; - case 'R': - cieInfo->pointerEncoding = addressSpace.get8(p); - ++p; - break; - case 'S': - cieInfo->isSignalFrame = true; - break; -#if defined(_LIBUNWIND_TARGET_AARCH64) - case 'B': - cieInfo->addressesSignedWithBKey = true; - break; -#endif - default: - // ignore unknown letters - break; - } - } - } - cieInfo->cieLength = cieContentEnd - cieInfo->cieStart; - cieInfo->cieInstructions = p; - return result; -} - - -/// "run" the DWARF instructions and create the abstact PrologInfo for an FDE -template -bool CFI_Parser::parseFDEInstructions(A &addressSpace, - const FDE_Info &fdeInfo, - const CIE_Info &cieInfo, pint_t upToPC, - int arch, PrologInfo *results) { - // clear results - memset(results, '\0', sizeof(PrologInfo)); - PrologInfoStackEntry *rememberStack = NULL; - - // parse CIE then FDE instructions - return parseInstructions(addressSpace, cieInfo.cieInstructions, - cieInfo.cieStart + cieInfo.cieLength, cieInfo, - (pint_t)(-1), rememberStack, arch, results) && - parseInstructions(addressSpace, fdeInfo.fdeInstructions, - fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, - upToPC - fdeInfo.pcStart, rememberStack, arch, - results); -} - -/// "run" the DWARF instructions -template -bool CFI_Parser::parseInstructions(A &addressSpace, pint_t instructions, - pint_t instructionsEnd, - const CIE_Info &cieInfo, pint_t pcoffset, - PrologInfoStackEntry *&rememberStack, - int arch, PrologInfo *results) { - pint_t p = instructions; - pint_t codeOffset = 0; - PrologInfo initialState = *results; - - _LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n", - static_cast(instructionsEnd)); - - // see DWARF Spec, section 6.4.2 for details on unwind opcodes - while ((p < instructionsEnd) && (codeOffset < pcoffset)) { - uint64_t reg; - uint64_t reg2; - int64_t offset; - uint64_t length; - uint8_t opcode = addressSpace.get8(p); - uint8_t operand; -#if !defined(_LIBUNWIND_NO_HEAP) - PrologInfoStackEntry *entry; -#endif - ++p; - switch (opcode) { - case DW_CFA_nop: - _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n"); - break; - case DW_CFA_set_loc: - codeOffset = - addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding); - _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n"); - break; - case DW_CFA_advance_loc1: - codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor); - p += 1; - _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n", - static_cast(codeOffset)); - break; - case DW_CFA_advance_loc2: - codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor); - p += 2; - _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n", - static_cast(codeOffset)); - break; - case DW_CFA_advance_loc4: - codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor); - p += 4; - _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n", - static_cast(codeOffset)); - break; - case DW_CFA_offset_extended: - reg = addressSpace.getULEB128(p, instructionsEnd); - offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) - * cieInfo.dataAlignFactor; - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG0( - "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); - return false; - } - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = offset; - _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", " - "offset=%" PRId64 ")\n", - reg, offset); - break; - case DW_CFA_restore_extended: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG0( - "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); - return false; - } - results->savedRegisters[reg] = initialState.savedRegisters[reg]; - _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg); - break; - case DW_CFA_undefined: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG0( - "malformed DW_CFA_undefined DWARF unwind, reg too big"); - return false; - } - results->savedRegisters[reg].location = kRegisterUnused; - _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); - break; - case DW_CFA_same_value: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG0( - "malformed DW_CFA_same_value DWARF unwind, reg too big"); - return false; - } - // DW_CFA_same_value unsupported - // "same value" means register was stored in frame, but its current - // value has not changed, so no need to restore from frame. - // We model this as if the register was never saved. - results->savedRegisters[reg].location = kRegisterUnused; - // set flag to disable conversion to compact unwind - results->sameValueUsed = true; - _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); - break; - case DW_CFA_register: - reg = addressSpace.getULEB128(p, instructionsEnd); - reg2 = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG0( - "malformed DW_CFA_register DWARF unwind, reg too big"); - return false; - } - if (reg2 > kMaxRegisterNumber) { - _LIBUNWIND_LOG0( - "malformed DW_CFA_register DWARF unwind, reg2 too big"); - return false; - } - results->savedRegisters[reg].location = kRegisterInRegister; - results->savedRegisters[reg].value = (int64_t)reg2; - // set flag to disable conversion to compact unwind - results->registersInOtherRegisters = true; - _LIBUNWIND_TRACE_DWARF( - "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2); - break; -#if !defined(_LIBUNWIND_NO_HEAP) - case DW_CFA_remember_state: - // avoid operator new, because that would be an upward dependency - entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry)); - if (entry != NULL) { - entry->next = rememberStack; - entry->info = *results; - rememberStack = entry; - } else { - return false; - } - _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n"); - break; - case DW_CFA_restore_state: - if (rememberStack != NULL) { - PrologInfoStackEntry *top = rememberStack; - *results = top->info; - rememberStack = top->next; - free((char *)top); - } else { - return false; - } - _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n"); - break; -#endif - case DW_CFA_def_cfa: - reg = addressSpace.getULEB128(p, instructionsEnd); - offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big"); - return false; - } - results->cfaRegister = (uint32_t)reg; - results->cfaRegisterOffset = (int32_t)offset; - _LIBUNWIND_TRACE_DWARF( - "DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n", reg, offset); - break; - case DW_CFA_def_cfa_register: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG0( - "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big"); - return false; - } - results->cfaRegister = (uint32_t)reg; - _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg); - break; - case DW_CFA_def_cfa_offset: - results->cfaRegisterOffset = (int32_t) - addressSpace.getULEB128(p, instructionsEnd); - results->codeOffsetAtStackDecrement = (uint32_t)codeOffset; - _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n", - results->cfaRegisterOffset); - break; - case DW_CFA_def_cfa_expression: - results->cfaRegister = 0; - results->cfaExpression = (int64_t)p; - length = addressSpace.getULEB128(p, instructionsEnd); - assert(length < static_cast(~0) && "pointer overflow"); - p += static_cast(length); - _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64 - ", length=%" PRIu64 ")\n", - results->cfaExpression, length); - break; - case DW_CFA_expression: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG0( - "malformed DW_CFA_expression DWARF unwind, reg too big"); - return false; - } - results->savedRegisters[reg].location = kRegisterAtExpression; - results->savedRegisters[reg].value = (int64_t)p; - length = addressSpace.getULEB128(p, instructionsEnd); - assert(length < static_cast(~0) && "pointer overflow"); - p += static_cast(length); - _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", " - "expression=0x%" PRIx64 ", " - "length=%" PRIu64 ")\n", - reg, results->savedRegisters[reg].value, length); - break; - case DW_CFA_offset_extended_sf: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG0( - "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big"); - return false; - } - offset = - addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = offset; - _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", " - "offset=%" PRId64 ")\n", - reg, offset); - break; - case DW_CFA_def_cfa_sf: - reg = addressSpace.getULEB128(p, instructionsEnd); - offset = - addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG0( - "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big"); - return false; - } - results->cfaRegister = (uint32_t)reg; - results->cfaRegisterOffset = (int32_t)offset; - _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", " - "offset=%" PRId64 ")\n", - reg, offset); - break; - case DW_CFA_def_cfa_offset_sf: - results->cfaRegisterOffset = (int32_t) - (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor); - results->codeOffsetAtStackDecrement = (uint32_t)codeOffset; - _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n", - results->cfaRegisterOffset); - break; - case DW_CFA_val_offset: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG( - "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64 - ") out of range\n", - reg); - return false; - } - offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) - * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterOffsetFromCFA; - results->savedRegisters[reg].value = offset; - _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", " - "offset=%" PRId64 "\n", - reg, offset); - break; - case DW_CFA_val_offset_sf: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG0( - "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big"); - return false; - } - offset = - addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterOffsetFromCFA; - results->savedRegisters[reg].value = offset; - _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", " - "offset=%" PRId64 "\n", - reg, offset); - break; - case DW_CFA_val_expression: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG0( - "malformed DW_CFA_val_expression DWARF unwind, reg too big"); - return false; - } - results->savedRegisters[reg].location = kRegisterIsExpression; - results->savedRegisters[reg].value = (int64_t)p; - length = addressSpace.getULEB128(p, instructionsEnd); - assert(length < static_cast(~0) && "pointer overflow"); - p += static_cast(length); - _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", " - "expression=0x%" PRIx64 ", length=%" PRIu64 ")\n", - reg, results->savedRegisters[reg].value, length); - break; - case DW_CFA_GNU_args_size: - length = addressSpace.getULEB128(p, instructionsEnd); - results->spExtraArgSize = (uint32_t)length; - _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length); - break; - case DW_CFA_GNU_negative_offset_extended: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF " - "unwind, reg too big"); - return false; - } - offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) - * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = -offset; - _LIBUNWIND_TRACE_DWARF( - "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); - break; - -#if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) - // The same constant is used to represent different instructions on - // AArch64 (negate_ra_state) and SPARC (window_save). - static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save, - "uses the same constant"); - case DW_CFA_AARCH64_negate_ra_state: - switch (arch) { -#if defined(_LIBUNWIND_TARGET_AARCH64) - case REGISTERS_ARM64: - results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^= 0x1; - _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); - break; -#endif -#if defined(_LIBUNWIND_TARGET_SPARC) - // case DW_CFA_GNU_window_save: - case REGISTERS_SPARC: - _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n"); - for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) { - results->savedRegisters[reg].location = kRegisterInRegister; - results->savedRegisters[reg].value = - ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0; - } - - for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = - ((int64_t)reg - UNW_SPARC_L0) * 4; - } - break; -#endif - } - break; -#else - (void)arch; -#endif - - default: - operand = opcode & 0x3F; - switch (opcode & 0xC0) { - case DW_CFA_offset: - reg = operand; - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64 - ") out of range", - reg); - return false; - } - offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) - * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = offset; - _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", - operand, offset); - break; - case DW_CFA_advance_loc: - codeOffset += operand * cieInfo.codeAlignFactor; - _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n", - static_cast(codeOffset)); - break; - case DW_CFA_restore: - reg = operand; - if (reg > kMaxRegisterNumber) { - _LIBUNWIND_LOG("malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64 - ") out of range", - reg); - return false; - } - results->savedRegisters[reg] = initialState.savedRegisters[reg]; - _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n", - static_cast(operand)); - break; - default: - _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode); - return false; - } - } - } - - return true; -} - -} // namespace libunwind - -#endif // __DWARF_PARSER_HPP__ Index: head/contrib/llvm/projects/libunwind/src/libunwind_ext.h =================================================================== --- head/contrib/llvm/projects/libunwind/src/libunwind_ext.h (revision 345067) +++ head/contrib/llvm/projects/libunwind/src/libunwind_ext.h (nonexistent) @@ -1,47 +0,0 @@ -//===------------------------ libunwind_ext.h -----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Extensions to libunwind API. -// -//===----------------------------------------------------------------------===// - -#ifndef __LIBUNWIND_EXT__ -#define __LIBUNWIND_EXT__ - -#include "config.h" -#include -#include - -#define UNW_STEP_SUCCESS 1 -#define UNW_STEP_END 0 - -#ifdef __cplusplus -extern "C" { -#endif -// SPI -extern void unw_iterate_dwarf_unwind_cache(void (*func)(unw_word_t ip_start, - unw_word_t ip_end, - unw_word_t fde, - unw_word_t mh)); - -// IPI -extern void _unw_add_dynamic_fde(unw_word_t fde); -extern void _unw_remove_dynamic_fde(unw_word_t fde); - -#if defined(_LIBUNWIND_ARM_EHABI) -extern const uint32_t* decode_eht_entry(const uint32_t*, size_t*, size_t*); -extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context, - const uint32_t *data, - size_t offset, size_t len); -#endif - -#ifdef __cplusplus -} -#endif - -#endif // __LIBUNWIND_EXT__ Property changes on: head/contrib/llvm/projects/libunwind/src/libunwind_ext.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind/LICENSE.TXT =================================================================== --- head/contrib/llvm/projects/libunwind/LICENSE.TXT (revision 345067) +++ head/contrib/llvm/projects/libunwind/LICENSE.TXT (nonexistent) @@ -1,76 +0,0 @@ -============================================================================== -libunwind License -============================================================================== - -The libunwind library is dual licensed under both the University of Illinois -"BSD-Like" license and the MIT license. As a user of this code you may choose -to use it under either license. As a contributor, you agree to allow your code -to be used under both. - -Full text of the relevant licenses is included below. - -============================================================================== - -University of Illinois/NCSA -Open Source License - -Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT - -All rights reserved. - -Developed by: - - LLVM Team - - University of Illinois at Urbana-Champaign - - http://llvm.org - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal with -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimers. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimers in the - documentation and/or other materials provided with the distribution. - - * Neither the names of the LLVM Team, University of Illinois at - Urbana-Champaign, nor the names of its contributors may be used to - endorse or promote products derived from this Software without specific - prior written permission. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE -SOFTWARE. - -============================================================================== - -Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. Property changes on: head/contrib/llvm/projects/libunwind/LICENSE.TXT ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/contrib/llvm/projects/libunwind =================================================================== --- head/contrib/llvm/projects/libunwind (revision 345067) +++ head/contrib/llvm/projects/libunwind (nonexistent) Property changes on: head/contrib/llvm/projects/libunwind ___________________________________________________________________ Deleted: svn:mergeinfo ## -0,20 +0,0 ## Reverse-merged /vendor/resolver/dist/contrib/llvm/projects/libunwind:r1540-186085 Reverse-merged /vendor/llvm-libunwind/dist-release_80:r344939-345018 Reverse-merged /projects/clang350-import/contrib/llvm/projects/libunwind:r274961-275126,275128-275133,275135-276476 Reverse-merged /projects/clang360-import/contrib/llvm/projects/libunwind:r277327-280030 Reverse-merged /projects/clang370-import/contrib/llvm/projects/libunwind:r287506-288928 Reverse-merged /projects/clang380-import/contrib/llvm/projects/libunwind:r292913-296412 Reverse-merged /projects/quota64/contrib/llvm/projects/libunwind:r184125-207707 Reverse-merged /projects/clang390-import/contrib/llvm/projects/libunwind:r303250-309123 Reverse-merged /projects/collation/contrib/llvm/projects/libunwind:r289256-290491 Reverse-merged /head/contrib/llvm/projects/libunwind:r283596-287501 Reverse-merged /projects/mpsutil/contrib/llvm/projects/libunwind:r290100 Reverse-merged /projects/largeSMP/contrib/llvm/projects/libunwind:r221273-222812,222815-223757 Reverse-merged /vendor/llvm-libunwind/dist:r288151-344967 Reverse-merged /projects/bsd_rdma_4_9/contrib/llvm/projects/libunwind:r319973-326168 Reverse-merged /vendor/llvm/dist/projects/libunwind:r208954-287519 Reverse-merged /projects/lldb-r201577/contrib/llvm/projects/libunwind:r262185-262527 Reverse-merged /projects/clang-trunk/contrib/llvm/projects/libunwind:r283596-287505 Reverse-merged /projects/multi-fibv6/head/contrib/llvm/projects/libunwind:r230929-231848 Reverse-merged /projects/clang400-import/contrib/llvm/projects/libunwind:r311132-314524 Reverse-merged /projects/clang-sparc64/contrib/llvm/projects/libunwind:r262258-262612 Index: head/lib/libgcc_eh/Makefile.inc =================================================================== --- head/lib/libgcc_eh/Makefile.inc (revision 345067) +++ head/lib/libgcc_eh/Makefile.inc (revision 345068) @@ -1,39 +1,39 @@ # $FreeBSD$ COMPILERRTDIR= ${SRCTOP}/contrib/compiler-rt -UNWINDINCDIR= ${SRCTOP}/contrib/llvm/projects/libunwind/include -UNWINDSRCDIR= ${SRCTOP}/contrib/llvm/projects/libunwind/src +UNWINDINCDIR= ${SRCTOP}/contrib/libunwind/include +UNWINDSRCDIR= ${SRCTOP}/contrib/libunwind/src STATIC_CFLAGS+=${PICFLAG} -fvisibility=hidden -DVISIBILITY_HIDDEN .PATH: ${COMPILERRTDIR}/lib/builtins .PATH: ${UNWINDSRCDIR} SRCS_EXC+= gcc_personality_v0.c SRCS_EXC+= int_util.c SRCS_EXC+= Unwind-EHABI.cpp SRCS_EXC+= Unwind-sjlj.c SRCS_EXC+= UnwindLevel1-gcc-ext.c SRCS_EXC+= UnwindLevel1.c SRCS_EXC+= UnwindRegistersRestore.S SRCS_EXC+= UnwindRegistersSave.S SRCS_EXC+= libunwind.cpp SRCS+= ${SRCS_EXC} .for file in ${SRCS_EXC:M*.c} CFLAGS.${file}+= -fno-exceptions -funwind-tables .endfor .for file in ${SRCS_EXC:M*.cpp} CXXFLAGS.${file}+= -fno-exceptions -funwind-tables .endfor CFLAGS+= -I${UNWINDINCDIR} -I${.CURDIR} -D_LIBUNWIND_IS_NATIVE_ONLY .if empty(CXXFLAGS:M-std=*) CXXFLAGS+= -std=c++11 .endif CXXFLAGS+= -fno-rtti STATIC_CXXFLAGS+= -fvisibility=hidden -fPIC # Probably need to just move this earlier or use CXXFLAGS .if ${MK_DIRDEPS_BUILD} == "yes" # Avoid dependency on lib/libc++ CFLAGS+= -isystem ${SRCTOP}/contrib/libc++/include -nostdinc++ .endif