Vendor import of stripped LLVM libunwind trunk r366426 (just before the

release_90 branch point):

https://llvm.org/svn/llvm-project/libunwind/trunk@366426
This commit is contained in:
Dimitry Andric 2019-08-20 20:51:22 +00:00
parent 8ef57cf97c
commit cd5ff43da5
27 changed files with 1172 additions and 964 deletions

View File

@ -1,5 +1,240 @@
==============================================================================
libunwind License
The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
==============================================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---- LLVM Exceptions to the Apache 2.0 License ----
As an exception, if, as a result of your compiling your source code, portions
of this Software are embedded into an Object form of such source code, you
may redistribute such embedded portions in such Object form without complying
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
In addition, if you combine or link compiled forms of this Software with
software that is licensed under the GPLv2 ("Combined Software") and if a
court of competent jurisdiction determines that the patent provision (Section
3), the indemnity provision (Section 9) or other Section of the License
conflicts with the conditions of the GPLv2, you may retroactively and
prospectively choose to deem waived or otherwise exclude such Section(s) of
the License, but only in their entirety and only with respect to the Combined
Software.
==============================================================================
Software from third parties included in the LLVM Project:
==============================================================================
The LLVM Project contains third party software which is under different license
terms. All such code will be identified clearly using at least one of two
mechanisms:
1) It will be in a separate directory tree with its own `LICENSE.txt` or
`LICENSE` file at the top containing the specific license and restrictions
which apply to that software, or
2) It will contain specific license and restriction terms at the top of every
file.
==============================================================================
Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
==============================================================================
The libunwind library is dual licensed under both the University of Illinois

View File

@ -1,9 +1,8 @@
//===------------------------- __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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

View File

@ -1,9 +1,8 @@
//===---------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Compatible with libunwind API documented at:
@ -76,7 +75,7 @@ typedef struct unw_addr_space *unw_addr_space_t;
typedef int unw_regnum_t;
typedef uintptr_t unw_word_t;
#if defined(__arm__)
#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
typedef uint64_t unw_fpreg_t;
#else
typedef double unw_fpreg_t;
@ -125,32 +124,6 @@ extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUN
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

View File

@ -1,9 +1,8 @@
//===------------------ 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Darwin's alternative to DWARF based unwind encodings.

View File

@ -1,13 +1,12 @@
//===------------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// C++ ABI Level 1 ABI documented at:
// http://mentorembedded.github.io/cxx-abi/abi-eh.html
// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
//
//===----------------------------------------------------------------------===//

View File

@ -1,9 +1,8 @@
//===------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Abstracts accessing local vs remote address spaces.
@ -28,6 +27,9 @@
#if _LIBUNWIND_USE_DLADDR
#include <dlfcn.h>
#if defined(__unix__) && defined(__ELF__) && defined(_LIBUNWIND_HAS_COMMENT_LIB_PRAGMA)
#pragma comment(lib, "dl")
#endif
#endif
#ifdef __APPLE__
@ -457,6 +459,8 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
// Don't even bother, since Windows has functions that do all this stuff
// for us.
(void)targetAddr;
(void)info;
return true;
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) && \
(__ANDROID_API__ < 21)
@ -534,11 +538,11 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
#endif
cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
*cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
hdrInfo);
cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
found_hdr = true;
if (found_hdr)
cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
}
}
@ -597,142 +601,15 @@ inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
return true;
}
}
#else
(void)addr;
(void)buf;
(void)bufLen;
(void)offset;
#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 <typename P>
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 <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) {
return *((uint8_t *)localCopy(addr));
}
template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) {
return P::E::get16(*(uint16_t *)localCopy(addr));
}
template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) {
return P::E::get32(*(uint32_t *)localCopy(addr));
}
template <typename P> uint64_t RemoteAddressSpace<P>::get64(pint_t addr) {
return P::E::get64(*(uint64_t *)localCopy(addr));
}
template <typename P>
typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) {
return P::getP(*(uint64_t *)localCopy(addr));
}
template <typename P>
typename P::uint_t OtherAddressSpace<P>::getRegister(pint_t addr) {
return P::getRegister(*(uint64_t *)localCopy(addr));
}
template <typename P>
uint64_t OtherAddressSpace<P>::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 <typename P>
int64_t RemoteAddressSpace<P>::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 <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) {
// FIX ME
}
template <typename P>
bool RemoteAddressSpace<P>::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<Pointer32<LittleEndian>> 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<Pointer64<LittleEndian>> 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<Pointer32<BigEndian>> 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<Pointer64<LittleEndian>> oas;
};
#endif // UNW_REMOTE
} // namespace libunwind
#endif // __ADDRESSSPACE_HPP__

View File

@ -1,9 +1,8 @@
//===-------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Does runtime stack unwinding using compact unwind encodings.

View File

@ -1,9 +1,8 @@
//===-------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Processor specific interpretation of DWARF unwind info.
@ -82,12 +81,11 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
const RegisterLocation &savedReg) {
switch (savedReg.location) {
case CFI_Parser<A>::kRegisterInCFA:
return addressSpace.getRegister(cfa + (pint_t)savedReg.value);
return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);
case CFI_Parser<A>::kRegisterAtExpression:
return addressSpace.getRegister(
evaluateExpression((pint_t)savedReg.value, addressSpace,
registers, cfa));
return (pint_t)addressSpace.getRegister(evaluateExpression(
(pint_t)savedReg.value, addressSpace, registers, cfa));
case CFI_Parser<A>::kRegisterIsExpression:
return evaluateExpression((pint_t)savedReg.value, addressSpace,
@ -234,6 +232,31 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
}
#endif
#if defined(_LIBUNWIND_TARGET_PPC64)
#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)
#define PPC64_ELFV1_R2_OFFSET 40
#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)
#define PPC64_ELFV2_R2_OFFSET 24
// If the instruction at return address is a TOC (r2) restore,
// then r2 was saved and needs to be restored.
// ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,
// while in ELFv1 ABI it is saved at SP + 40.
if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) {
pint_t sp = newRegisters.getRegister(UNW_REG_SP);
pint_t r2 = 0;
switch (addressSpace.get32(returnAddress)) {
case PPC64_ELFV1_R2_LOAD_INST_ENCODING:
r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET);
break;
case PPC64_ELFV2_R2_LOAD_INST_ENCODING:
r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);
break;
}
if (r2)
newRegisters.setRegister(UNW_PPC64_R2, r2);
}
#endif
// Return address is address after call site instruction, so setting IP to
// that does simualates a return.
newRegisters.setIP(returnAddress);

View File

@ -1,9 +1,8 @@
//===--------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Parses DWARF CFIs (FDEs and CIEs).

View File

@ -1,9 +1,8 @@
//===------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Parses ELF .eh_frame_hdr sections.
@ -36,7 +35,7 @@ template <typename A> class EHHeaderParser {
uint8_t table_enc;
};
static void decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd,
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,
@ -53,12 +52,14 @@ template <typename A> class EHHeaderParser {
};
template <typename A>
void EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
bool EHHeaderParser<A>::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_ABORT("Unsupported .eh_frame_hdr version");
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++);
@ -71,6 +72,8 @@ void EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
? 0
: addressSpace.getEncodedP(p, ehHdrEnd, fde_count_enc, ehHdrStart);
ehHdrInfo.table = p;
return true;
}
template <typename A>
@ -102,7 +105,9 @@ bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,
pint_t ehHdrEnd = ehHdrStart + sectionLength;
EHHeaderParser<A>::EHHeaderInfo hdrInfo;
EHHeaderParser<A>::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd, hdrInfo);
if (!EHHeaderParser<A>::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd,
hdrInfo))
return false;
size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc);
pint_t tableEntry;

View File

@ -1,9 +1,8 @@
//===----------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Abstract interface to shared reader/writer log, hiding platform and
@ -18,6 +17,9 @@
#include <windows.h>
#elif !defined(_LIBUNWIND_HAS_NO_THREADS)
#include <pthread.h>
#if defined(__unix__) && defined(__ELF__) && defined(_LIBUNWIND_HAS_COMMENT_LIB_PRAGMA)
#pragma comment(lib, "pthread")
#endif
#endif
namespace libunwind {
@ -57,11 +59,11 @@ class _LIBUNWIND_HIDDEN RWMutex {
SRWLOCK _lock = SRWLOCK_INIT;
};
#else
#elif !defined(LIBUNWIND_USE_WEAK_PTHREAD)
class _LIBUNWIND_HIDDEN RWMutex {
public:
bool lock_shared() { return pthread_rwlock_rdlock(&_lock) == 0; }
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; }
@ -70,6 +72,41 @@ class _LIBUNWIND_HIDDEN RWMutex {
pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER;
};
#else
extern "C" int __attribute__((weak))
pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg);
extern "C" int __attribute__((weak))
pthread_rwlock_rdlock(pthread_rwlock_t *lock);
extern "C" int __attribute__((weak))
pthread_rwlock_wrlock(pthread_rwlock_t *lock);
extern "C" int __attribute__((weak))
pthread_rwlock_unlock(pthread_rwlock_t *lock);
// Calls to the locking functions are gated on pthread_create, and not the
// functions themselves, because the data structure should only be locked if
// another thread has been created. This is what similar libraries do.
class _LIBUNWIND_HIDDEN RWMutex {
public:
bool lock_shared() {
return !pthread_create || (pthread_rwlock_rdlock(&_lock) == 0);
}
bool unlock_shared() {
return !pthread_create || (pthread_rwlock_unlock(&_lock) == 0);
}
bool lock() {
return !pthread_create || (pthread_rwlock_wrlock(&_lock) == 0);
}
bool unlock() {
return !pthread_create || (pthread_rwlock_unlock(&_lock) == 0);
}
private:
pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER;
};
#endif
} // namespace libunwind

View File

@ -1,9 +1,8 @@
//===----------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Models register sets for supported processors.
@ -2104,16 +2103,16 @@ class _LIBUNWIND_HIDDEN Registers_arm {
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*);
static void saveVFPWithFSTMD(void*);
static void saveVFPWithFSTMX(void*);
static void saveVFPv3(void*);
static void restoreVFPWithFLDMD(void*);
static void restoreVFPWithFLDMX(void*);
static void restoreVFPv3(void*);
#if defined(__ARM_WMMX)
static void saveiWMMX(unw_fpreg_t*);
static void saveiWMMX(void*);
static void saveiWMMXControl(uint32_t*);
static void restoreiWMMX(unw_fpreg_t*);
static void restoreiWMMX(void*);
static void restoreiWMMXControl(uint32_t*);
#endif
void restoreCoreAndJumpTo();
@ -2155,7 +2154,7 @@ inline Registers_arm::Registers_arm(const void *registers)
_saved_vfp_d16_d31(false) {
static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
"arm registers do not fit into unw_context_t");
// See unw_getcontext() note about data.
// 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));
@ -2434,7 +2433,7 @@ inline const char *Registers_arm::getRegisterName(int regNum) {
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.
// __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))

View File

@ -1,9 +1,8 @@
//===--------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements ARM zero-cost C++ exceptions
@ -21,8 +20,6 @@
#include <stdlib.h>
#include <string.h>
#include <type_traits>
#include "config.h"
#include "libunwind.h"
#include "libunwind_ext.h"
@ -34,7 +31,11 @@ namespace {
// signinficant byte.
uint8_t getByte(const uint32_t* data, size_t offset) {
const uint8_t* byteData = reinterpret_cast<const uint8_t*>(data);
#ifdef __LITTLE_ENDIAN__
return byteData[(offset & ~(size_t)0x03) + (3 - (offset & (size_t)0x03))];
#else
return byteData[offset];
#endif
}
const char* getNextWord(const char* data, uint32_t* out) {
@ -182,7 +183,7 @@ static _Unwind_Reason_Code unwindOneFrame(_Unwind_State state,
if (result != _URC_CONTINUE_UNWIND)
return result;
if (unw_step(reinterpret_cast<unw_cursor_t*>(context)) != UNW_STEP_SUCCESS)
if (__unw_step(reinterpret_cast<unw_cursor_t *>(context)) != UNW_STEP_SUCCESS)
return _URC_FAILURE;
return _URC_CONTINUE_UNWIND;
}
@ -443,17 +444,18 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
// 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);
__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<void *>(exception_object));
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<void *>(exception_object));
return _URC_FATAL_PHASE1_ERROR;
}
@ -462,12 +464,12 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
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);
__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,
@ -537,7 +539,7 @@ 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);
__unw_init_local(cursor, uc);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
static_cast<void *>(exception_object));
@ -559,19 +561,20 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor
// 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);
__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<void *>(exception_object));
__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<void *>(exception_object));
return _URC_FATAL_PHASE2_ERROR;
}
@ -580,8 +583,8 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
_LIBUNWIND_TRACE_UNWINDING(
@ -625,8 +628,8 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor
// 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);
__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<void *>(exception_object),
@ -637,11 +640,11 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor
// 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);
__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.
__unw_resume(cursor);
// __unw_resume() only returns if there was an error.
return _URC_FATAL_PHASE2_ERROR;
// # EHABI #7.4.3
@ -670,7 +673,7 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
static_cast<void *>(exception_object));
unw_context_t uc;
unw_cursor_t cursor;
unw_getcontext(&uc);
__unw_getcontext(&uc);
// This field for is for compatibility with GCC to say this isn't a forced
// unwind. EHABI #7.2
@ -708,7 +711,7 @@ _Unwind_Resume(_Unwind_Exception *exception_object) {
static_cast<void *>(exception_object));
unw_context_t uc;
unw_cursor_t cursor;
unw_getcontext(&uc);
__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.
@ -725,7 +728,7 @@ _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)
if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
result = (uintptr_t)frameInfo.lsda;
_LIBUNWIND_TRACE_API(
"_Unwind_GetLanguageSpecificData(context=%p) => 0x%llx",
@ -765,8 +768,8 @@ _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass 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
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:
@ -776,28 +779,28 @@ _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
// Can only touch d0-15 with FSTMFDX.
if (regno > 15)
return _UVRSR_FAILED;
unw_save_vfp_as_X(cursor);
__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
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
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
return __unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno),
*(unw_fpreg_t *)valuep) == UNW_ESUCCESS
? _UVRSR_OK
: _UVRSR_FAILED;
#else
@ -819,8 +822,8 @@ _Unwind_VRS_Get_Internal(_Unwind_Context *context,
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
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:
@ -830,28 +833,28 @@ _Unwind_VRS_Get_Internal(_Unwind_Context *context,
// Can only touch d0-15 with FSTMFDX.
if (regno > 15)
return _UVRSR_FAILED;
unw_save_vfp_as_X(cursor);
__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
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
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
return __unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno),
(unw_fpreg_t *)valuep) == UNW_ESUCCESS
? _UVRSR_OK
: _UVRSR_FAILED;
#else
@ -960,7 +963,7 @@ _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)
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<void *>(context), (long long)result);
@ -983,7 +986,7 @@ 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)
if (__unw_step(cursor) != UNW_STEP_SUCCESS)
return _URC_FAILURE;
return _URC_OK;
}

View File

@ -1,9 +1,8 @@
//===------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
//===----------------------------------------------------------------------===//

View File

@ -1,9 +1,8 @@
//===--------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@ -53,14 +52,16 @@ 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) {
(void)urc;
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);
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:
@ -69,7 +70,6 @@ static void _unw_seh_set_disp_ctx(unw_cursor_t *cursor, DISPATCHER_CONTEXT *disp
_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;
@ -78,7 +78,9 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
uintptr_t retval, target;
bool ours = false;
_LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler(%#010x(%x), %p)", ms_exc->ExceptionCode, ms_exc->ExceptionFlags, frame);
_LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler(%#010lx(%lx), %p)",
ms_exc->ExceptionCode, ms_exc->ExceptionFlags,
(void *)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
@ -112,9 +114,9 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
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);
__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)) {
@ -130,7 +132,10 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
}
}
_LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() calling personality function %p(1, %d, %llx, %p, %p)", pers, action, exc->exception_class, exc, ctx);
_LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() calling personality "
"function %p(1, %d, %llx, %p, %p)",
(void *)pers, action, exc->exception_class,
(void *)exc, (void *)ctx);
urc = pers(1, action, exc->exception_class, exc, ctx);
_LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() personality returned %d", urc);
switch (urc) {
@ -168,18 +173,18 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
_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]);
__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]);
__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]);
__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);
__unw_get_reg(&cursor, UNW_REG_IP, &target);
ms_exc->ExceptionCode = STATUS_GCC_UNWIND;
#ifdef __x86_64__
ms_exc->ExceptionInformation[2] = disp->TargetIp;
@ -199,7 +204,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
}
}
/// Personality function returned by \c unw_get_proc_info() in SEH contexts.
/// 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()).
@ -207,6 +212,8 @@ extern "C" _Unwind_Reason_Code
__libunwind_seh_personality(int version, _Unwind_Action state,
uint64_t klass, _Unwind_Exception *exc,
struct _Unwind_Context *context) {
(void)version;
(void)klass;
EXCEPTION_RECORD ms_exc;
bool phase2 = (state & (_UA_SEARCH_PHASE|_UA_CLEANUP_PHASE)) == _UA_CLEANUP_PHASE;
ms_exc.ExceptionCode = STATUS_GCC_THROW;
@ -215,7 +222,8 @@ __libunwind_seh_personality(int version, _Unwind_Action state,
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);
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,
@ -234,15 +242,15 @@ 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);
__unw_init_local(&cursor2, uc);
// Walk each frame until we reach where search phase said to stop
while (unw_step(&cursor2) > 0) {
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 "
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;
@ -253,8 +261,8 @@ unwind_phase2_forced(unw_context_t *uc,
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
if ((__unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
_LIBUNWIND_TRACE_UNWINDING(
@ -304,7 +312,7 @@ unwind_phase2_forced(unw_context_t *uc,
"_URC_INSTALL_CONTEXT",
(void *)exception_object);
// We may get control back if landing pad calls _Unwind_Resume().
unw_resume(&cursor2);
__unw_resume(&cursor2);
break;
default:
// Personality routine returned an unknown result code.
@ -369,7 +377,7 @@ _Unwind_Resume(_Unwind_Exception *exception_object) {
if (exception_object->private_[0] != 0) {
unw_context_t uc;
unw_getcontext(&uc);
__unw_getcontext(&uc);
unwind_phase2_forced(&uc, exception_object,
(_Unwind_Stop_Fn) exception_object->private_[0],
(void *)exception_object->private_[4]);
@ -407,7 +415,7 @@ _Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
_LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",
(void *)exception_object, (void *)(uintptr_t)stop);
unw_context_t uc;
unw_getcontext(&uc);
__unw_getcontext(&uc);
// Mark that this is a forced unwind, so _Unwind_Resume() can do
// the right thing.
@ -421,7 +429,8 @@ _Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
/// 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;
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);
@ -432,30 +441,32 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
/// function.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
DISPATCHER_CONTEXT *disp = _unw_seh_get_disp_ctx((unw_cursor_t *)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) {
static int __unw_init_seh(unw_cursor_t *cursor, CONTEXT *context) {
#ifdef _LIBUNWIND_TARGET_X86_64
new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86_64>(
context, LocalAddressSpace::sThisAddressSpace);
new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor))
UnwindCursor<LocalAddressSpace, Registers_x86_64>(
context, LocalAddressSpace::sThisAddressSpace);
auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
co->setInfoBasedOnIPRegister();
return UNW_ESUCCESS;
#elif defined(_LIBUNWIND_TARGET_ARM)
new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm>(
context, LocalAddressSpace::sThisAddressSpace);
new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor))
UnwindCursor<LocalAddressSpace, Registers_arm>(
context, LocalAddressSpace::sThisAddressSpace);
auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
co->setInfoBasedOnIPRegister();
return UNW_ESUCCESS;
#elif defined(_LIBUNWIND_TARGET_AARCH64)
new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm64>(
context, LocalAddressSpace::sThisAddressSpace);
new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor))
UnwindCursor<LocalAddressSpace, Registers_arm64>(
context, LocalAddressSpace::sThisAddressSpace);
auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
co->setInfoBasedOnIPRegister();
return UNW_ESUCCESS;
@ -464,8 +475,7 @@ _unw_init_seh(unw_cursor_t *cursor, CONTEXT *context) {
#endif
}
static DISPATCHER_CONTEXT *
_unw_seh_get_disp_ctx(unw_cursor_t *cursor) {
static DISPATCHER_CONTEXT *__unw_seh_get_disp_ctx(unw_cursor_t *cursor) {
#ifdef _LIBUNWIND_TARGET_X86_64
return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->getDispatcherContext();
#elif defined(_LIBUNWIND_TARGET_ARM)
@ -477,8 +487,8 @@ _unw_seh_get_disp_ctx(unw_cursor_t *cursor) {
#endif
}
static void
_unw_seh_set_disp_ctx(unw_cursor_t *cursor, DISPATCHER_CONTEXT *disp) {
static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor,
DISPATCHER_CONTEXT *disp) {
#ifdef _LIBUNWIND_TARGET_X86_64
reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->setDispatcherContext(disp);
#elif defined(_LIBUNWIND_TARGET_ARM)

View File

@ -1,9 +1,8 @@
//===--------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements setjump-longjump based C++ exceptions
@ -12,6 +11,7 @@
#include <unwind.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
@ -52,7 +52,7 @@ struct _Unwind_FunctionContext {
#else
# if __STDC_VERSION__ >= 201112L
# define _LIBUNWIND_THREAD_LOCAL _Thread_local
# elif defined(_WIN32)
# elif defined(_MSC_VER)
# define _LIBUNWIND_THREAD_LOCAL __declspec(thread)
# elif defined(__GNUC__) || defined(__clang__)
# define _LIBUNWIND_THREAD_LOCAL __thread
@ -108,7 +108,8 @@ _Unwind_SjLj_Unregister(struct _Unwind_FunctionContext *fc) {
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);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p",
(void *)c);
// walk each frame looking for a place to stop
for (bool handlerNotFound = true; handlerNotFound; c = c->prev) {
@ -117,17 +118,18 @@ unwind_phase1(struct _Unwind_Exception *exception_object) {
if (c == NULL) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): reached "
"bottom => _URC_END_OF_STACK",
exception_object);
(void *)exception_object);
return _URC_END_OF_STACK;
}
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", c);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", (void *)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);
"personality function %p",
(void *)exception_object,
(void *)c->personality);
_Unwind_Reason_Code personalityResult = (*c->personality)(
1, _UA_SEARCH_PHASE, exception_object->exception_class,
exception_object, (struct _Unwind_Context *)c);
@ -138,12 +140,14 @@ unwind_phase1(struct _Unwind_Exception *exception_object) {
handlerNotFound = false;
exception_object->private_2 = (uintptr_t) c;
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
"_URC_HANDLER_FOUND", exception_object);
"_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", exception_object);
"_URC_CONTINUE_UNWIND",
(void *)exception_object);
// continue unwinding
break;
@ -151,7 +155,7 @@ unwind_phase1(struct _Unwind_Exception *exception_object) {
// something went wrong
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
exception_object);
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
}
}
@ -162,19 +166,21 @@ unwind_phase1(struct _Unwind_Exception *exception_object) {
static _Unwind_Reason_Code
unwind_phase2(struct _Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", exception_object);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
(void *)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);
(void *)exception_object, (void *)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);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): __unw_step() reached "
"bottom => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_END_OF_STACK;
}
@ -194,7 +200,7 @@ unwind_phase2(struct _Unwind_Exception *exception_object) {
// continue unwinding
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
exception_object);
(void *)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 "
@ -203,14 +209,14 @@ unwind_phase2(struct _Unwind_Exception *exception_object) {
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]);
"_URC_INSTALL_CONTEXT, will resume at "
"landing pad %p",
(void *)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
// __unw_resume() only returns if there was an error
return _URC_FATAL_PHASE2_ERROR;
default:
// something went wrong
@ -237,9 +243,10 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
// 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);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): __unw_step() reached "
"bottom => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_END_OF_STACK;
}
@ -251,11 +258,11 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
(struct _Unwind_Context *)c, stop_parameter);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"stop function returned %d",
exception_object, stopResult);
(void *)exception_object, stopResult);
if (stopResult != _URC_NO_REASON) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"stopped by stop function",
exception_object);
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
@ -264,7 +271,7 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
__personality_routine p = (__personality_routine) c->personality;
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"calling personality function %p",
exception_object, p);
(void *)exception_object, (void *)p);
_Unwind_Reason_Code personalityResult =
(*p)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)c);
@ -272,13 +279,13 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned _URC_CONTINUE_UNWIND",
exception_object);
(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",
exception_object);
(void *)exception_object);
// we may get control back if landing pad calls _Unwind_Resume()
__Unwind_SjLj_SetTopOfFunctionStack(c);
__builtin_longjmp(c->jbuf, 1);
@ -288,7 +295,7 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned %d, "
"_URC_FATAL_PHASE2_ERROR",
exception_object, personalityResult);
(void *)exception_object, personalityResult);
return _URC_FATAL_PHASE2_ERROR;
}
}
@ -298,8 +305,8 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
// 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);
"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,
@ -314,7 +321,8 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
/// 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);
_LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)",
(void *)exception_object);
// mark that this is a non-forced unwind, so _Unwind_Resume() can do the right
// thing
@ -344,7 +352,8 @@ _Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) {
/// __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);
_LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)",
(void *)exception_object);
if (exception_object->private_1 != 0)
unwind_phase2_forced(exception_object,
@ -362,8 +371,8 @@ _Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) {
_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);
"private_1=%" PRIuPTR,
(void *)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.
@ -386,7 +395,8 @@ _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);
"=> 0x%" PRIuPTR,
(void *)context, ufc->lsda);
return ufc->lsda;
}
@ -394,8 +404,8 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
/// 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);
_LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)", (void *)context,
index);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
return ufc->resumeParameters[index];
}
@ -404,8 +414,9 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
/// 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);
_LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIuPTR
")",
(void *)context, index, new_value);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
ufc->resumeParameters[index] = new_value;
}
@ -414,8 +425,8 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
/// 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);
_LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIu32,
(void *)context, ufc->resumeLocation + 1);
return ufc->resumeLocation + 1;
}
@ -427,8 +438,9 @@ _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);
_LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIu32,
(void *)context, (void *)ipBefore,
ufc->resumeLocation + 1);
return ufc->resumeLocation + 1;
}
@ -436,8 +448,8 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
/// 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);
_LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIuPTR ")",
(void *)context, new_value);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
ufc->resumeLocation = new_value - 1;
}
@ -449,7 +461,7 @@ _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);
_LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)", (void *)context);
return 0;
}
@ -459,7 +471,7 @@ _Unwind_GetRegionStart(struct _Unwind_Context *context) {
_LIBUNWIND_EXPORT void
_Unwind_DeleteException(struct _Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
exception_object);
(void *)exception_object);
if (exception_object->exception_cleanup != NULL)
(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
exception_object);
@ -473,7 +485,7 @@ _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_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context);
_LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
}
@ -484,14 +496,14 @@ _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_TRACE_API("_Unwind_GetTextRelBase(context=%p)", (void *)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);
_LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)", (void *)context);
if (context != NULL) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
// Setjmp/longjmp based exceptions don't have a true CFA.

View File

@ -1,9 +1,8 @@
//===------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// C++ interface to lower levels of libunwind
@ -12,7 +11,6 @@
#ifndef __UNWINDCURSOR_HPP__
#define __UNWINDCURSOR_HPP__
#include <algorithm>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@ -106,7 +104,6 @@ class _LIBUNWIND_HIDDEN DwarfFDECache {
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;
@ -485,6 +482,10 @@ class UnwindCursor : public AbstractUnwindCursor {
DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; }
void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; }
// libunwind does not and should not depend on C++ library which means that we
// need our own defition of inline placement new.
static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
private:
pint_t getLastPC() const { return _dispContext.ControlPc; }
@ -789,6 +790,8 @@ bool UnwindCursor<A, R>::validFloatReg(int regNum) {
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;
#else
(void)regNum;
#endif
return false;
}
@ -816,6 +819,7 @@ unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
#elif defined(_LIBUNWIND_TARGET_AARCH64)
return _msContext.V[regNum - UNW_ARM64_D0].D[0];
#else
(void)regNum;
_LIBUNWIND_ABORT("float registers unimplemented");
#endif
}
@ -843,6 +847,8 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
#elif defined(_LIBUNWIND_TARGET_AARCH64)
_msContext.V[regNum - UNW_ARM64_D0].D[0] = value;
#else
(void)regNum;
(void)value;
_LIBUNWIND_ABORT("float registers unimplemented");
#endif
}
@ -892,6 +898,10 @@ class UnwindCursor : public AbstractUnwindCursor{
virtual void saveVFPAsX();
#endif
// libunwind does not and should not depend on C++ library which means that we
// need our own defition of inline placement new.
static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
private:
#if defined(_LIBUNWIND_ARM_EHABI)
@ -1221,7 +1231,6 @@ template<typename A>
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;
@ -1275,6 +1284,29 @@ struct EHABISectionIterator {
const UnwindInfoSections* _sects;
};
namespace {
template <typename A>
EHABISectionIterator<A> EHABISectionUpperBound(
EHABISectionIterator<A> first,
EHABISectionIterator<A> last,
typename A::pint_t value) {
size_t len = last - first;
while (len > 0) {
size_t l2 = len / 2;
EHABISectionIterator<A> m = first + l2;
if (value < *m) {
len = l2;
} else {
first = ++m;
len -= l2 + 1;
}
}
return first;
}
}
template <typename A, typename R>
bool UnwindCursor<A, R>::getInfoFromEHABISection(
pint_t pc,
@ -1286,7 +1318,7 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection(
if (begin == end)
return false;
EHABISectionIterator<A> itNextPC = std::upper_bound(begin, end, pc);
EHABISectionIterator<A> itNextPC = EHABISectionUpperBound(begin, end, pc);
if (itNextPC == begin)
return false;
EHABISectionIterator<A> itThisPC = itNextPC - 1;
@ -1296,8 +1328,7 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection(
// 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<pint_t>::max()
: itNextPC.functionAddress();
pint_t nextPC = (itNextPC == end) ? UINTPTR_MAX : itNextPC.functionAddress();
pint_t indexDataAddr = itThisPC.dataAddress();
if (indexDataAddr == 0)
@ -1709,7 +1740,7 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
--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",
"but personality table has only %d entries",
encoding, personalityIndex,
sectionHeader.personalityArrayCount());
return false;

View File

@ -1,9 +1,8 @@
//===--------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements gcc extensions to the C++ ABI Exception Handling Level 1.
@ -94,10 +93,10 @@ _LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *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)
__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;
@ -109,8 +108,8 @@ _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);
__unw_getcontext(&uc);
__unw_init_local(&cursor, &uc);
_LIBUNWIND_TRACE_API("_Unwind_Backtrace(callback=%p)",
(void *)(uintptr_t)callback);
@ -129,7 +128,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
#if !defined(_LIBUNWIND_ARM_EHABI)
// ask libunwind to get next frame (skip over first frame which is
// _Unwind_Backtrace())
if (unw_step(&cursor) <= 0) {
if (__unw_step(&cursor) <= 0) {
_LIBUNWIND_TRACE_UNWINDING(" _backtrace: ended because cursor reached "
"bottom of stack, returning %d",
_URC_END_OF_STACK);
@ -138,7 +137,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
#else
// Get the information for this frame.
unw_proc_info_t frameInfo;
if (unw_get_proc_info(&cursor, &frameInfo) != UNW_ESUCCESS) {
if (__unw_get_proc_info(&cursor, &frameInfo) != UNW_ESUCCESS) {
return _URC_END_OF_STACK;
}
@ -165,8 +164,8 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
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);
__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,
@ -192,10 +191,10 @@ _LIBUNWIND_EXPORT const void *_Unwind_Find_FDE(const void *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);
__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;
@ -209,7 +208,7 @@ _LIBUNWIND_EXPORT const void *_Unwind_Find_FDE(const void *pc,
_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);
__unw_get_reg(cursor, UNW_REG_SP, &result);
_LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p) => 0x%" PRIxPTR,
(void *)context, result);
return (uintptr_t)result;
@ -234,7 +233,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
/// 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);
__unw_add_dynamic_fde((unw_word_t)(uintptr_t)fde);
}
@ -244,7 +243,7 @@ _LIBUNWIND_EXPORT void __register_frame(const void *fde) {
/// 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);
__unw_remove_dynamic_fde((unw_word_t)(uintptr_t)fde);
}

View File

@ -1,13 +1,12 @@
//===------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements C++ ABI Exception Handling Level 1 as documented at:
// http://mentorembedded.github.io/cxx-abi/abi-eh.html
// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
// using libunwind
//
//===----------------------------------------------------------------------===//
@ -26,9 +25,10 @@
#include <stdio.h>
#include <string.h>
#include "libunwind.h"
#include "unwind.h"
#include "config.h"
#include "libunwind.h"
#include "libunwind_ext.h"
#include "unwind.h"
#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__)
@ -36,33 +36,36 @@
static _Unwind_Reason_Code
unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
unw_init_local(cursor, uc);
__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);
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);
_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);
_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);
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;
}
@ -71,12 +74,12 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
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);
__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 "",
@ -100,7 +103,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
// 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);
__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",
@ -129,7 +132,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
static _Unwind_Reason_Code
unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
unw_init_local(cursor, uc);
__unw_init_local(cursor, uc);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
(void *)exception_object);
@ -139,27 +142,30 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
// Ask libunwind to get next frame (skip over first which is
// _Unwind_RaiseException).
int stepResult = unw_step(cursor);
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);
_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);
_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);
__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;
}
@ -168,8 +174,8 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
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
@ -212,15 +218,15 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
// 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);
__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.
__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.
@ -240,15 +246,15 @@ 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);
__unw_init_local(cursor, uc);
// Walk each frame until we reach where search phase said to stop
while (unw_step(cursor) > 0) {
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 "
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;
@ -259,8 +265,8 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
_LIBUNWIND_TRACE_UNWINDING(
@ -310,7 +316,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
"_URC_INSTALL_CONTEXT",
(void *)exception_object);
// We may get control back if landing pad calls _Unwind_Resume().
unw_resume(cursor);
__unw_resume(cursor);
break;
default:
// Personality routine returned an unknown result code.
@ -346,7 +352,7 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
(void *)exception_object);
unw_context_t uc;
unw_cursor_t cursor;
unw_getcontext(&uc);
__unw_getcontext(&uc);
// Mark that this is a non-forced unwind, so _Unwind_Resume()
// can do the right thing.
@ -380,7 +386,7 @@ _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);
__unw_getcontext(&uc);
if (exception_object->private_1 != 0)
unwind_phase2_forced(&uc, &cursor, exception_object,
@ -405,7 +411,7 @@ _Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
(void *)exception_object, (void *)(uintptr_t)stop);
unw_context_t uc;
unw_cursor_t cursor;
unw_getcontext(&uc);
__unw_getcontext(&uc);
// Mark that this is a forced unwind, so _Unwind_Resume() can do
// the right thing.
@ -423,7 +429,7 @@ _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)
if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
result = (uintptr_t)frameInfo.lsda;
_LIBUNWIND_TRACE_API(
"_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,
@ -444,7 +450,7 @@ _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)
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);
@ -469,7 +475,7 @@ _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);
__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;
@ -482,14 +488,14 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
")",
(void *)context, index, value);
unw_cursor_t *cursor = (unw_cursor_t *)context;
unw_set_reg(cursor, index, value);
__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);
__unw_get_reg(cursor, UNW_REG_IP, &result);
_LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,
(void *)context, result);
return (uintptr_t)result;
@ -503,7 +509,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
_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);
__unw_set_reg(cursor, UNW_REG_IP, value);
}
#endif // !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__)

View File

@ -1,9 +1,8 @@
//===-------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@ -14,7 +13,7 @@
#if !defined(__USING_SJLJ_EXCEPTIONS__)
#if defined(__i386__)
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv)
#
# void libunwind::Registers_x86::jumpto()
#
@ -61,7 +60,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv)
#elif defined(__x86_64__)
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv)
#
# void libunwind::Registers_x86_64::jumpto()
#
@ -130,7 +129,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv)
#elif defined(__powerpc64__)
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
//
// void libunwind::Registers_ppc64::jumpto()
//
@ -395,120 +394,120 @@ Lnovec:
#elif defined(__ppc__)
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
;
; void libunwind::Registers_ppc::jumpto()
;
; On entry:
; thread_state pointer is in r3
;
DEFINE_LIBUNWIND_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 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 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
// 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:
andis. %r0, %r5, (1<<(15-_index)) SEPARATOR \
beq Ldone ## _index SEPARATOR \
lwz %r0, 424+_index*16(%r3) SEPARATOR \
stw %r0, 0(%r4) SEPARATOR \
lwz %r0, 424+_index*16+4(%r3) SEPARATOR \
stw %r0, 4(%r4) SEPARATOR \
lwz %r0, 424+_index*16+8(%r3) SEPARATOR \
stw %r0, 8(%r4) SEPARATOR \
lwz %r0, 424+_index*16+12(%r3) SEPARATOR \
stw %r0, 12(%r4) SEPARATOR \
lvx %v ## _index, 0, %r4 SEPARATOR \
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:
andi. %r0, %r5, (1<<(31-_index)) SEPARATOR \
beq Ldone ## _index SEPARATOR \
lwz %r0, 424+_index*16(%r3) SEPARATOR \
stw %r0, 0(%r4) SEPARATOR \
lwz %r0, 424+_index*16+4(%r3) SEPARATOR \
stw %r0, 4(%r4) SEPARATOR \
lwz %r0, 424+_index*16+8(%r3) SEPARATOR \
stw %r0, 8(%r4) SEPARATOR \
lwz %r0, 424+_index*16+12(%r3) SEPARATOR \
stw %r0, 12(%r4) SEPARATOR \
lvx %v ## _index, 0, %r4 SEPARATOR \
Ldone ## _index:
LOAD_VECTOR_UNALIGNEDl(0)
@ -545,17 +544,17 @@ Ldone ## _index:
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
lwz %r0, 136(%r3) // __cr
mtcr %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__)
@ -567,7 +566,7 @@ Lnovec:
// thread_state pointer is in x0
//
.p2align 2
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
// skip restore of x0,x1 for now
ldp x2, x3, [x0, #0x010]
ldp x4, x5, [x0, #0x020]
@ -576,7 +575,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
ldp x10,x11, [x0, #0x050]
ldp x12,x13, [x0, #0x060]
ldp x14,x15, [x0, #0x070]
ldp x16,x17, [x0, #0x080]
// x16 and x17 were clobbered by the call into the unwinder, so no point in
// restoring them.
ldp x18,x19, [x0, #0x090]
ldp x20,x21, [x0, #0x0A0]
ldp x22,x23, [x0, #0x0B0]
@ -584,8 +584,6 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
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]
@ -605,12 +603,21 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
ldr d30, [x0, #0x200]
ldr d31, [x0, #0x208]
// Finally, restore sp. This must be done after the the last read from the
// context struct, because it is allocated on the stack, and an exception
// could clobber the de-allocated portion of the stack after sp has been
// restored.
ldr x16, [x0, #0x0F8]
ldp x0, x1, [x0, #0x000] // restore x0,x1
mov sp,x16 // restore sp
ret x30 // jump to pc
#elif defined(__arm__) && !defined(__APPLE__)
#if !defined(__ARM_ARCH_ISA_ARM)
#if (__ARM_ARCH_ISA_THUMB == 2)
.syntax unified
#endif
.thumb
#endif
@ -621,7 +628,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
@ thread_state pointer is in r0
@
.p2align 2
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv)
DEFINE_LIBUNWIND_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
@ -659,7 +666,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJu
#if defined(__ELF__)
.fpu vfpv3-d16
#endif
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPy)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPv)
@ 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
@ -680,7 +687,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFL
#if defined(__ELF__)
.fpu vfpv3-d16
#endif
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPy)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPv)
vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia
JMP(lr)
@ -694,7 +701,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFL
#if defined(__ELF__)
.fpu vfpv3
#endif
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPv)
vldmia r0, {d16-d31}
JMP(lr)
@ -710,7 +717,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy)
#if defined(__ELF__)
.arch armv5te
#endif
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPv)
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
@ -739,7 +746,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy)
#if defined(__ELF__)
.arch armv5te
#endif
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj)
DEFINE_LIBUNWIND_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
@ -750,7 +757,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXCont
#elif defined(__or1k__)
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
#
# void libunwind::Registers_or1k::jumpto()
#
@ -809,7 +816,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
// On entry:
// thread state pointer is in a0 ($4)
//
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
.set push
.set noat
.set noreorder
@ -918,7 +925,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
// On entry:
// thread state pointer is in a0 ($4)
//
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
.set push
.set noat
.set noreorder
@ -1008,7 +1015,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
// On entry:
// thread_state pointer is in o0
//
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv)
ta 3
ldd [%o0 + 64], %l0
ldd [%o0 + 72], %l2

View File

@ -1,9 +1,8 @@
//===------------------------ 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@ -16,7 +15,7 @@
#if defined(__i386__)
#
# extern int unw_getcontext(unw_context_t* thread_state)
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# On entry:
# + +
@ -27,7 +26,7 @@
# +-----------------------+ <-- SP
# + +
#
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
push %eax
movl 8(%esp), %eax
movl %ebx, 4(%eax)
@ -57,12 +56,12 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
#elif defined(__x86_64__)
#
# extern int unw_getcontext(unw_context_t* thread_state)
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# On entry:
# thread_state pointer is in rdi
#
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
#if defined(_WIN64)
#define PTR %rcx
#define TMP %rdx
@ -119,12 +118,12 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
#
# extern int unw_getcontext(unw_context_t* thread_state)
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# On entry:
# thread_state pointer is in a0 ($4)
#
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
.set push
.set noat
.set noreorder
@ -228,12 +227,12 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
#elif defined(__mips64)
#
# extern int unw_getcontext(unw_context_t* thread_state)
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# On entry:
# thread_state pointer is in a0 ($4)
#
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
.set push
.set noat
.set noreorder
@ -318,21 +317,21 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
# elif defined(__mips__)
#
# extern int unw_getcontext(unw_context_t* thread_state)
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# Just trap for the time being.
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
teq $0, $0
#elif defined(__powerpc64__)
//
// extern int unw_getcontext(unw_context_t* thread_state)
// extern int __unw_getcontext(unw_context_t* thread_state)
//
// On entry:
// thread_state pointer is in r3
//
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
// store register (GPR)
#define PPC64_STR(n) \
@ -557,157 +556,157 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
#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)
//
// 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 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 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
// 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
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)
stvx _vec, 0, %r4 SEPARATOR \
lwz %r5, 0(%r4) SEPARATOR \
stw %r5, _offset(%r3) SEPARATOR \
lwz %r5, 4(%r4) SEPARATOR \
stw %r5, _offset+4(%r3) SEPARATOR \
lwz %r5, 8(%r4) SEPARATOR \
stw %r5, _offset+8(%r3) SEPARATOR \
lwz %r5, 12(%r4) SEPARATOR \
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)
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
li %r3, 0 // return UNW_ESUCCESS
blr
#elif defined(__arm64__) || defined(__aarch64__)
//
// extern int unw_getcontext(unw_context_t* thread_state)
// extern int __unw_getcontext(unw_context_t* thread_state)
//
// On entry:
// thread_state pointer is in x0
//
.p2align 2
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
stp x0, x1, [x0, #0x000]
stp x2, x3, [x0, #0x010]
stp x4, x5, [x0, #0x020]
@ -751,11 +750,14 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
#elif defined(__arm__) && !defined(__APPLE__)
#if !defined(__ARM_ARCH_ISA_ARM)
#if (__ARM_ARCH_ISA_THUMB == 2)
.syntax unified
#endif
.thumb
#endif
@
@ extern int unw_getcontext(unw_context_t* thread_state)
@ extern int __unw_getcontext(unw_context_t* thread_state)
@
@ On entry:
@ thread_state pointer is in r0
@ -764,10 +766,10 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
@ 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.
@ Instead, VFP registers are demand saved by logic external to __unw_getcontext.
@
.p2align 2
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
stm r0!, {r0-r7}
mov r1, r8
@ -808,7 +810,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
#if defined(__ELF__)
.fpu vfpv3-d16
#endif
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPv)
vstmia r0, {d0-d15}
JMP(lr)
@ -822,7 +824,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMD
#if defined(__ELF__)
.fpu vfpv3-d16
#endif
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPv)
vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
JMP(lr)
@ -836,7 +838,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMX
#if defined(__ELF__)
.fpu vfpv3
#endif
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPv)
@ 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
@ -859,7 +861,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
#if defined(__ELF__)
.arch armv5te
#endif
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPv)
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
@ -888,7 +890,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
#if defined(__ELF__)
.arch armv5te
#endif
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
DEFINE_LIBUNWIND_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
@ -900,12 +902,12 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControl
#elif defined(__or1k__)
#
# extern int unw_getcontext(unw_context_t* thread_state)
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# On entry:
# thread_state pointer is in r3
#
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
l.sw 0(r3), r0
l.sw 4(r3), r1
l.sw 8(r3), r2
@ -946,12 +948,12 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
#elif defined(__sparc__)
#
# extern int unw_getcontext(unw_context_t* thread_state)
# extern int __unw_getcontext(unw_context_t* thread_state)
#
# On entry:
# thread_state pointer is in o0
#
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
ta 3
add %o7, 8, %o7
std %g0, [%o0 + 0]
@ -973,6 +975,9 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
jmp %o7
clr %o0 // return UNW_ESUCCESS
#endif
WEAK_ALIAS(__unw_getcontext, unw_getcontext)
#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
NO_EXEC_STACK_DIRECTIVE

View File

@ -1,9 +1,8 @@
//===--------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
//===----------------------------------------------------------------------===//

View File

@ -1,9 +1,8 @@
/* ===-- 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.
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
* See https://llvm.org/LICENSE.txt for license information.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
* ===----------------------------------------------------------------------===
*
@ -29,14 +28,26 @@
#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
#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1)
#define PPC64_OPD1 .section .opd,"aw",@progbits SEPARATOR
#define PPC64_OPD2 SEPARATOR \
.p2align 3 SEPARATOR \
.quad .Lfunc_begin0 SEPARATOR \
.quad .TOC.@tocbase SEPARATOR \
.quad 0 SEPARATOR \
.text SEPARATOR \
.Lfunc_begin0:
#else
#define PPC64_OPD1
#define PPC64_OPD2
#endif
#define GLUE2(a, b) a ## b
#define GLUE(a, b) GLUE2(a, b)
#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
@ -46,6 +57,12 @@
#define SYMBOL_IS_FUNC(name)
#define EXPORT_SYMBOL(name)
#define HIDDEN_SYMBOL(name) .private_extern name
#define WEAK_SYMBOL(name) .weak_reference name
#define WEAK_ALIAS(name, aliasname) \
.globl SYMBOL_NAME(aliasname) SEPARATOR \
WEAK_SYMBOL(aliasname) SEPARATOR \
SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
#define NO_EXEC_STACK_DIRECTIVE
#elif defined(__ELF__)
@ -57,6 +74,10 @@
#endif
#define EXPORT_SYMBOL(name)
#define HIDDEN_SYMBOL(name) .hidden name
#define WEAK_SYMBOL(name) .weak name
#define WEAK_ALIAS(name, aliasname) \
WEAK_SYMBOL(aliasname) SEPARATOR \
SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
defined(__linux__)
@ -72,9 +93,9 @@
.scl 2 SEPARATOR \
.type 32 SEPARATOR \
.endef
#define EXPORT_SYMBOL2(name) \
.section .drectve,"yn" SEPARATOR \
.ascii "-export:", #name, "\0" SEPARATOR \
#define EXPORT_SYMBOL2(name) \
.section .drectve,"yn" SEPARATOR \
.ascii "-export:", #name, "\0" SEPARATOR \
.text
#if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS)
#define EXPORT_SYMBOL(name)
@ -83,6 +104,23 @@
#endif
#define HIDDEN_SYMBOL(name)
#if defined(__MINGW32__)
#define WEAK_ALIAS(name, aliasname) \
.globl SYMBOL_NAME(aliasname) SEPARATOR \
EXPORT_SYMBOL(aliasname) SEPARATOR \
SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
#else
#define WEAK_ALIAS3(name, aliasname) \
.section .drectve,"yn" SEPARATOR \
.ascii "-alternatename:", #aliasname, "=", #name, "\0" SEPARATOR \
.text
#define WEAK_ALIAS2(name, aliasname) \
WEAK_ALIAS3(name, aliasname)
#define WEAK_ALIAS(name, aliasname) \
EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
WEAK_ALIAS2(SYMBOL_NAME(name), SYMBOL_NAME(aliasname))
#endif
#define NO_EXEC_STACK_DIRECTIVE
#elif defined(__sparc__)
@ -93,17 +131,13 @@
#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):
#define DEFINE_LIBUNWIND_FUNCTION(name) \
.globl SYMBOL_NAME(name) SEPARATOR \
HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
PPC64_OPD1 \
SYMBOL_NAME(name): \
PPC64_OPD2
#if defined(__arm__)
#if !defined(__ARM_ARCH)

View File

@ -1,9 +1,8 @@
//===----------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Defines macros used within libunwind project.
@ -63,6 +62,35 @@
#endif
#endif
#define STR(a) #a
#define XSTR(a) STR(a)
#define SYMBOL_NAME(name) XSTR(__USER_LABEL_PREFIX__) #name
#if defined(__APPLE__)
#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
__asm__(".globl " SYMBOL_NAME(aliasname)); \
__asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \
extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \
__attribute__((weak_import));
#elif defined(__ELF__)
#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \
__attribute__((weak, alias(#name)));
#elif defined(_WIN32)
#if defined(__MINGW32__)
#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \
__attribute__((alias(#name)));
#else
#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
__pragma(comment(linker, "/alternatename:" SYMBOL_NAME(aliasname) "=" \
SYMBOL_NAME(name))) \
extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname;
#endif
#else
#error Unsupported target
#endif
#if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__)
#define _LIBUNWIND_BUILD_SJLJ_APIS
#endif

View File

@ -1,9 +1,8 @@
//===------------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

View File

@ -1,9 +1,8 @@
//===--------------------------- 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements unw_* functions from <libunwind.h>
@ -12,12 +11,6 @@
#include <libunwind.h>
#ifndef NDEBUG
#include <cstdlib> // getenv
#endif
#include <new>
#include <algorithm>
#include "libunwind_ext.h"
#include "config.h"
@ -36,15 +29,11 @@ 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)",
/// __unw_getcontext().
_LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor,
unw_context_t *context) {
_LIBUNWIND_TRACE_API("__unw_init_local(cursor=%p, context=%p)",
static_cast<void *>(cursor),
static_cast<void *>(context));
#if defined(__i386__)
@ -73,101 +62,21 @@ _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
# error Architecture not supported
#endif
// Use "placement new" to allocate UnwindCursor in the cursor buffer.
new ((void *)cursor) UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
context, LocalAddressSpace::sThisAddressSpace);
new (reinterpret_cast<UnwindCursor<LocalAddressSpace, REGISTER_KIND> *>(cursor))
UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
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<RemoteAddressSpace<Pointer32<LittleEndian>>,
Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg);
break;
case CPU_TYPE_X86_64:
new ((void *)cursor)
UnwindCursor<RemoteAddressSpace<Pointer64<LittleEndian>>,
Registers_x86_64>(((unw_addr_space_x86_64 *)as)->oas, arg);
break;
case CPU_TYPE_POWERPC:
new ((void *)cursor)
UnwindCursor<RemoteAddressSpace<Pointer32<BigEndian>>,
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
_LIBUNWIND_WEAK_ALIAS(__unw_init_local, unw_init_local)
/// 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)",
_LIBUNWIND_HIDDEN 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<void *>(cursor), regNum,
static_cast<void *>(value));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
@ -177,12 +86,13 @@ _LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
}
return UNW_EBADREG;
}
_LIBUNWIND_WEAK_ALIAS(__unw_get_reg, unw_get_reg)
/// 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 ")",
_LIBUNWIND_HIDDEN 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<void *>(cursor), regNum, value);
typedef LocalAddressSpace::pint_t pint_t;
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
@ -208,12 +118,12 @@ _LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
}
return UNW_EBADREG;
}
_LIBUNWIND_WEAK_ALIAS(__unw_set_reg, unw_set_reg)
/// 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)",
_LIBUNWIND_HIDDEN 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<void *>(cursor), regNum,
static_cast<void *>(value));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
@ -223,16 +133,16 @@ _LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
}
return UNW_EBADREG;
}
_LIBUNWIND_WEAK_ALIAS(__unw_get_fpreg, unw_get_fpreg)
/// 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) {
_LIBUNWIND_HIDDEN 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)",
_LIBUNWIND_TRACE_API("__unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)",
static_cast<void *>(cursor), regNum, value);
#else
_LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)",
_LIBUNWIND_TRACE_API("__unw_set_fpreg(cursor=%p, regNum=%d, value=%g)",
static_cast<void *>(cursor), regNum, value);
#endif
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
@ -242,20 +152,20 @@ _LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
}
return UNW_EBADREG;
}
_LIBUNWIND_WEAK_ALIAS(__unw_set_fpreg, unw_set_fpreg)
/// Move cursor to next frame.
_LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) {
_LIBUNWIND_TRACE_API("unw_step(cursor=%p)", static_cast<void *>(cursor));
_LIBUNWIND_HIDDEN int __unw_step(unw_cursor_t *cursor) {
_LIBUNWIND_TRACE_API("__unw_step(cursor=%p)", static_cast<void *>(cursor));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->step();
}
_LIBUNWIND_WEAK_ALIAS(__unw_step, unw_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)",
_LIBUNWIND_HIDDEN 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<void *>(cursor), static_cast<void *>(info));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
co->getInfo(info);
@ -264,21 +174,21 @@ _LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor,
else
return UNW_ESUCCESS;
}
_LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info, unw_get_proc_info)
/// 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<void *>(cursor));
_LIBUNWIND_HIDDEN int __unw_resume(unw_cursor_t *cursor) {
_LIBUNWIND_TRACE_API("__unw_resume(cursor=%p)", static_cast<void *>(cursor));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
co->jumpto();
return UNW_EUNSPEC;
}
_LIBUNWIND_WEAK_ALIAS(__unw_resume, unw_resume)
/// 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)",
_LIBUNWIND_HIDDEN 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<void *>(cursor), static_cast<void *>(buf),
static_cast<unsigned long>(bufLen));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
@ -287,58 +197,62 @@ _LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf,
else
return UNW_EUNSPEC;
}
_LIBUNWIND_WEAK_ALIAS(__unw_get_proc_name, unw_get_proc_name)
/// 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)",
_LIBUNWIND_HIDDEN int __unw_is_fpreg(unw_cursor_t *cursor,
unw_regnum_t regNum) {
_LIBUNWIND_TRACE_API("__unw_is_fpreg(cursor=%p, regNum=%d)",
static_cast<void *>(cursor), regNum);
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->validFloatReg(regNum);
}
_LIBUNWIND_WEAK_ALIAS(__unw_is_fpreg, unw_is_fpreg)
/// 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)",
_LIBUNWIND_HIDDEN const char *__unw_regname(unw_cursor_t *cursor,
unw_regnum_t regNum) {
_LIBUNWIND_TRACE_API("__unw_regname(cursor=%p, regNum=%d)",
static_cast<void *>(cursor), regNum);
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->getRegisterName(regNum);
}
_LIBUNWIND_WEAK_ALIAS(__unw_regname, unw_regname)
/// 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)",
_LIBUNWIND_HIDDEN int __unw_is_signal_frame(unw_cursor_t *cursor) {
_LIBUNWIND_TRACE_API("__unw_is_signal_frame(cursor=%p)",
static_cast<void *>(cursor));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->isSignalFrame();
}
_LIBUNWIND_WEAK_ALIAS(__unw_is_signal_frame, unw_is_signal_frame)
#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)",
_LIBUNWIND_HIDDEN void __unw_save_vfp_as_X(unw_cursor_t *cursor) {
_LIBUNWIND_TRACE_API("__unw_get_fpreg_save_vfp_as_X(cursor=%p)",
static_cast<void *>(cursor));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->saveVFPAsX();
}
_LIBUNWIND_WEAK_ALIAS(__unw_save_vfp_as_X, unw_save_vfp_as_X)
#endif
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
/// SPI: walks cached DWARF entries
_LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)(
_LIBUNWIND_HIDDEN 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)",
_LIBUNWIND_TRACE_API("__unw_iterate_dwarf_unwind_cache(func=%p)",
reinterpret_cast<void *>(func));
DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
}
_LIBUNWIND_WEAK_ALIAS(__unw_iterate_dwarf_unwind_cache,
unw_iterate_dwarf_unwind_cache)
/// IPI: for __register_frame()
void _unw_add_dynamic_fde(unw_word_t fde) {
void __unw_add_dynamic_fde(unw_word_t fde) {
CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
const char *message = CFI_Parser<LocalAddressSpace>::decodeFDE(
@ -352,12 +266,12 @@ void _unw_add_dynamic_fde(unw_word_t fde) {
fdeInfo.pcStart, fdeInfo.pcEnd,
fdeInfo.fdeStart);
} else {
_LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message);
_LIBUNWIND_DEBUG_LOG("__unw_add_dynamic_fde: bad fde: %s", message);
}
}
/// IPI: for __deregister_frame()
void _unw_remove_dynamic_fde(unw_word_t fde) {
void __unw_remove_dynamic_fde(unw_word_t fde) {
// fde is own mh_group
DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
}

View File

@ -1,9 +1,8 @@
//===------------------------ 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.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Extensions to libunwind API.
@ -23,15 +22,34 @@
#ifdef __cplusplus
extern "C" {
#endif
extern int __unw_getcontext(unw_context_t *);
extern int __unw_init_local(unw_cursor_t *, unw_context_t *);
extern int __unw_step(unw_cursor_t *);
extern int __unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *);
extern int __unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *);
extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t);
extern int __unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t);
extern int __unw_resume(unw_cursor_t *);
#ifdef __arm__
/* Save VFP registers in FSTMX format (instead of FSTMD). */
extern void __unw_save_vfp_as_X(unw_cursor_t *);
#endif
extern const char *__unw_regname(unw_cursor_t *, unw_regnum_t);
extern int __unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *);
extern int __unw_is_fpreg(unw_cursor_t *, unw_regnum_t);
extern int __unw_is_signal_frame(unw_cursor_t *);
extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *);
// 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));
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);
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*);