Merge libunwind trunk r366426, resolve conflicts, and add FREEBSD-Xlist.
This commit is contained in:
commit
d8053d0817
11
contrib/libunwind/FREEBSD-Xlist
Normal file
11
contrib/libunwind/FREEBSD-Xlist
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
.arcconfig
|
||||
.clang-format
|
||||
CMakeLists.txt
|
||||
cmake
|
||||
cmake/
|
||||
docs
|
||||
docs/
|
||||
src/CMakeLists.txt
|
||||
test
|
||||
test/
|
@ -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
|
||||
|
@ -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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -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)
|
||||
@ -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__
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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).
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
@ -2105,16 +2104,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();
|
||||
@ -2156,7 +2155,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));
|
||||
@ -2435,7 +2434,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))
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
@ -1227,7 +1237,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;
|
||||
@ -1281,6 +1290,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,
|
||||
@ -1292,7 +1324,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;
|
||||
@ -1302,8 +1334,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)
|
||||
@ -1715,7 +1746,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;
|
||||
|
@ -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;
|
||||
@ -275,7 +274,7 @@ _LIBUNWIND_EXPORT void __deregister_frame(const void *addr) {
|
||||
/// 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);
|
||||
}
|
||||
|
||||
|
||||
@ -285,7 +284,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);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -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__)
|
||||
|
@ -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,7 +394,7 @@ Lnovec:
|
||||
|
||||
#elif defined(__ppc__)
|
||||
|
||||
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
|
||||
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
|
||||
//
|
||||
// void libunwind::Registers_ppc::jumpto()
|
||||
//
|
||||
@ -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()
|
||||
#
|
||||
@ -890,7 +897,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv)
|
||||
// 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
|
||||
@ -999,7 +1006,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
|
||||
@ -1089,7 +1096,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
|
||||
|
@ -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) \
|
||||
@ -563,7 +562,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
|
||||
// On entry:
|
||||
// thread_state pointer is in r3
|
||||
//
|
||||
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
|
||||
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
|
||||
stw %r0, 8(%r3)
|
||||
mflr %r0
|
||||
stw %r0, 0(%r3) // store lr as ssr0
|
||||
@ -701,13 +700,13 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
|
||||
#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
|
||||
@ -1026,12 +1028,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]
|
||||
@ -1053,6 +1055,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
|
||||
|
@ -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
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
@ -58,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__)
|
||||
@ -69,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__)
|
||||
@ -84,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)
|
||||
@ -95,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__)
|
||||
@ -105,20 +131,12 @@
|
||||
|
||||
#endif
|
||||
|
||||
#define DEFINE_LIBUNWIND_FUNCTION(name) \
|
||||
.globl SYMBOL_NAME(name) SEPARATOR \
|
||||
EXPORT_SYMBOL(name) SEPARATOR \
|
||||
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
|
||||
PPC64_OPD1 \
|
||||
SYMBOL_NAME(name): \
|
||||
PPC64_OPD2
|
||||
|
||||
#define DEFINE_LIBUNWIND_PRIVATE_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): \
|
||||
#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__)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -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__)
|
||||
@ -75,101 +64,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;
|
||||
@ -179,12 +88,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;
|
||||
@ -210,12 +120,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;
|
||||
@ -225,16 +135,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;
|
||||
@ -244,20 +154,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);
|
||||
@ -266,21 +176,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;
|
||||
@ -289,58 +199,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(
|
||||
@ -354,12 +268,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);
|
||||
}
|
||||
|
@ -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*);
|
||||
|
Loading…
Reference in New Issue
Block a user