1eb8650a7SLouis Dionne //===----------------------------------------------------------------------===//
2b1b19117SSaleem Abdulrasool //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b1b19117SSaleem Abdulrasool //
7b1b19117SSaleem Abdulrasool //
8b1b19117SSaleem Abdulrasool // Implements unw_* functions from <libunwind.h>
9b1b19117SSaleem Abdulrasool //
10b1b19117SSaleem Abdulrasool //===----------------------------------------------------------------------===//
11b1b19117SSaleem Abdulrasool
12b1b19117SSaleem Abdulrasool #include <libunwind.h>
13b1b19117SSaleem Abdulrasool
14b1b19117SSaleem Abdulrasool #include "config.h"
1521b25a1fSgejin #include "libunwind_ext.h"
16b1b19117SSaleem Abdulrasool
17b1b19117SSaleem Abdulrasool #include <stdlib.h>
18b1b19117SSaleem Abdulrasool
19e03be2efSSaleem Abdulrasool // Define the __has_feature extension for compilers that do not support it so
20e03be2efSSaleem Abdulrasool // that we can later check for the presence of ASan in a compiler-neutral way.
21e03be2efSSaleem Abdulrasool #if !defined(__has_feature)
22e03be2efSSaleem Abdulrasool #define __has_feature(feature) 0
23e03be2efSSaleem Abdulrasool #endif
24e03be2efSSaleem Abdulrasool
25e03be2efSSaleem Abdulrasool #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
26adf1561dSShoaib Meenai #include <sanitizer/asan_interface.h>
27adf1561dSShoaib Meenai #endif
28b1b19117SSaleem Abdulrasool
29b51c49aaSMartin Storsjo #if !defined(__USING_SJLJ_EXCEPTIONS__)
30e2de03fdSEd Schouten #include "AddressSpace.hpp"
31b1b19117SSaleem Abdulrasool #include "UnwindCursor.hpp"
32b1b19117SSaleem Abdulrasool
33b1b19117SSaleem Abdulrasool using namespace libunwind;
34b1b19117SSaleem Abdulrasool
35b1b19117SSaleem Abdulrasool /// internal object to represent this processes address space
36b1b19117SSaleem Abdulrasool LocalAddressSpace LocalAddressSpace::sThisAddressSpace;
37b1b19117SSaleem Abdulrasool
38b1b19117SSaleem Abdulrasool _LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space =
39b1b19117SSaleem Abdulrasool (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace;
40b1b19117SSaleem Abdulrasool
41b1b19117SSaleem Abdulrasool /// Create a cursor of a thread in this process given 'context' recorded by
42e369a989SPetr Hosek /// __unw_getcontext().
__unw_init_local(unw_cursor_t * cursor,unw_context_t * context)43e369a989SPetr Hosek _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor,
44b1b19117SSaleem Abdulrasool unw_context_t *context) {
45e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_init_local(cursor=%p, context=%p)",
46b1b19117SSaleem Abdulrasool static_cast<void *>(cursor),
47b1b19117SSaleem Abdulrasool static_cast<void *>(context));
48b1b19117SSaleem Abdulrasool #if defined(__i386__)
4954387eefSAsiri Rathnayake # define REGISTER_KIND Registers_x86
50b1b19117SSaleem Abdulrasool #elif defined(__x86_64__)
5154387eefSAsiri Rathnayake # define REGISTER_KIND Registers_x86_64
527c907061SMartin Storsjo #elif defined(__powerpc64__)
537c907061SMartin Storsjo # define REGISTER_KIND Registers_ppc64
54cd20e579SSam James #elif defined(__powerpc__)
5554387eefSAsiri Rathnayake # define REGISTER_KIND Registers_ppc
5654387eefSAsiri Rathnayake #elif defined(__aarch64__)
5754387eefSAsiri Rathnayake # define REGISTER_KIND Registers_arm64
586a3ed9bfSMartin Storsjo #elif defined(__arm__)
5954387eefSAsiri Rathnayake # define REGISTER_KIND Registers_arm
60ce4c5c98SPeter Zotov #elif defined(__or1k__)
6154387eefSAsiri Rathnayake # define REGISTER_KIND Registers_or1k
629107594fSBrian Cain #elif defined(__hexagon__)
639107594fSBrian Cain # define REGISTER_KIND Registers_hexagon
64c3f240f7SJohn Baldwin #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
65dfbbbdf8SJohn Baldwin # define REGISTER_KIND Registers_mips_o32
66c3f240f7SJohn Baldwin #elif defined(__mips64)
6740bab375SJohn Baldwin # define REGISTER_KIND Registers_mips_newabi
688518eb54SVasileios Kalintiris #elif defined(__mips__)
69dfbbbdf8SJohn Baldwin # warning The MIPS architecture is not supported with this ABI and environment!
702b9554b8SKoakuma #elif defined(__sparc__) && defined(__arch64__)
712b9554b8SKoakuma #define REGISTER_KIND Registers_sparc64
7217121adfSDaniel Cederman #elif defined(__sparc__)
7317121adfSDaniel Cederman # define REGISTER_KIND Registers_sparc
74b17d4643SKamlesh Kumar #elif defined(__riscv)
75ce3d1c6dSSam Elliott # define REGISTER_KIND Registers_riscv
763cbd476cSKazushi (Jam) Marukawa #elif defined(__ve__)
773cbd476cSKazushi (Jam) Marukawa # define REGISTER_KIND Registers_ve
78*364c5023SUlrich Weigand #elif defined(__s390x__)
79*364c5023SUlrich Weigand # define REGISTER_KIND Registers_s390x
80ef766a7eSEd Maste #else
81ef766a7eSEd Maste # error Architecture not supported
82b1b19117SSaleem Abdulrasool #endif
8354387eefSAsiri Rathnayake // Use "placement new" to allocate UnwindCursor in the cursor buffer.
845745e908SPetr Hosek new (reinterpret_cast<UnwindCursor<LocalAddressSpace, REGISTER_KIND> *>(cursor))
855745e908SPetr Hosek UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
8654387eefSAsiri Rathnayake context, LocalAddressSpace::sThisAddressSpace);
8754387eefSAsiri Rathnayake #undef REGISTER_KIND
88b1b19117SSaleem Abdulrasool AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
89b1b19117SSaleem Abdulrasool co->setInfoBasedOnIPRegister();
90b1b19117SSaleem Abdulrasool
91b1b19117SSaleem Abdulrasool return UNW_ESUCCESS;
92b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_init_local,unw_init_local)93e369a989SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_init_local, unw_init_local)
94b1b19117SSaleem Abdulrasool
95b1b19117SSaleem Abdulrasool /// Get value of specified register at cursor position in stack frame.
96e369a989SPetr Hosek _LIBUNWIND_HIDDEN int __unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
97b1b19117SSaleem Abdulrasool unw_word_t *value) {
98e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_get_reg(cursor=%p, regNum=%d, &value=%p)",
99b1b19117SSaleem Abdulrasool static_cast<void *>(cursor), regNum,
100b1b19117SSaleem Abdulrasool static_cast<void *>(value));
101b1b19117SSaleem Abdulrasool AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
102b1b19117SSaleem Abdulrasool if (co->validReg(regNum)) {
103b1b19117SSaleem Abdulrasool *value = co->getReg(regNum);
104b1b19117SSaleem Abdulrasool return UNW_ESUCCESS;
105b1b19117SSaleem Abdulrasool }
106b1b19117SSaleem Abdulrasool return UNW_EBADREG;
107b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_get_reg,unw_get_reg)108e369a989SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_get_reg, unw_get_reg)
109b1b19117SSaleem Abdulrasool
110b1b19117SSaleem Abdulrasool /// Set value of specified register at cursor position in stack frame.
111e369a989SPetr Hosek _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
112b1b19117SSaleem Abdulrasool unw_word_t value) {
113e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_set_reg(cursor=%p, regNum=%d, value=0x%" PRIxPTR
114e369a989SPetr Hosek ")",
115c18d5c05SMartin Storsjo static_cast<void *>(cursor), regNum, value);
116b1b19117SSaleem Abdulrasool typedef LocalAddressSpace::pint_t pint_t;
117b1b19117SSaleem Abdulrasool AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
118b1b19117SSaleem Abdulrasool if (co->validReg(regNum)) {
119b1b19117SSaleem Abdulrasool co->setReg(regNum, (pint_t)value);
120b1b19117SSaleem Abdulrasool // specical case altering IP to re-find info (being called by personality
121b1b19117SSaleem Abdulrasool // function)
122d0166a0aSJoerg Sonnenberger if (regNum == UNW_REG_IP) {
123d0166a0aSJoerg Sonnenberger unw_proc_info_t info;
124d0166a0aSJoerg Sonnenberger // First, get the FDE for the old location and then update it.
125d0166a0aSJoerg Sonnenberger co->getInfo(&info);
126b1b19117SSaleem Abdulrasool co->setInfoBasedOnIPRegister(false);
127d0166a0aSJoerg Sonnenberger // If the original call expects stack adjustment, perform this now.
128d0166a0aSJoerg Sonnenberger // Normal frame unwinding would have included the offset already in the
129d0166a0aSJoerg Sonnenberger // CFA computation.
130d0166a0aSJoerg Sonnenberger // Note: for PA-RISC and other platforms where the stack grows up,
131d0166a0aSJoerg Sonnenberger // this should actually be - info.gp. LLVM doesn't currently support
132d0166a0aSJoerg Sonnenberger // any such platforms and Clang doesn't export a macro for them.
133d0166a0aSJoerg Sonnenberger if (info.gp)
134d0166a0aSJoerg Sonnenberger co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp);
135d0166a0aSJoerg Sonnenberger }
136b1b19117SSaleem Abdulrasool return UNW_ESUCCESS;
137b1b19117SSaleem Abdulrasool }
138b1b19117SSaleem Abdulrasool return UNW_EBADREG;
139b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_set_reg,unw_set_reg)140e369a989SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_set_reg, unw_set_reg)
141b1b19117SSaleem Abdulrasool
142b1b19117SSaleem Abdulrasool /// Get value of specified float register at cursor position in stack frame.
143e369a989SPetr Hosek _LIBUNWIND_HIDDEN int __unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
144b1b19117SSaleem Abdulrasool unw_fpreg_t *value) {
145e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)",
146b1b19117SSaleem Abdulrasool static_cast<void *>(cursor), regNum,
147b1b19117SSaleem Abdulrasool static_cast<void *>(value));
148b1b19117SSaleem Abdulrasool AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
149b1b19117SSaleem Abdulrasool if (co->validFloatReg(regNum)) {
150b1b19117SSaleem Abdulrasool *value = co->getFloatReg(regNum);
151b1b19117SSaleem Abdulrasool return UNW_ESUCCESS;
152b1b19117SSaleem Abdulrasool }
153b1b19117SSaleem Abdulrasool return UNW_EBADREG;
154b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_get_fpreg,unw_get_fpreg)155e369a989SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_get_fpreg, unw_get_fpreg)
156b1b19117SSaleem Abdulrasool
157b1b19117SSaleem Abdulrasool /// Set value of specified float register at cursor position in stack frame.
158e369a989SPetr Hosek _LIBUNWIND_HIDDEN int __unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
159b1b19117SSaleem Abdulrasool unw_fpreg_t value) {
1605808011bSRanjeet Singh #if defined(_LIBUNWIND_ARM_EHABI)
161e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)",
162b1b19117SSaleem Abdulrasool static_cast<void *>(cursor), regNum, value);
163b1b19117SSaleem Abdulrasool #else
164e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_set_fpreg(cursor=%p, regNum=%d, value=%g)",
165b1b19117SSaleem Abdulrasool static_cast<void *>(cursor), regNum, value);
166b1b19117SSaleem Abdulrasool #endif
167b1b19117SSaleem Abdulrasool AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
168b1b19117SSaleem Abdulrasool if (co->validFloatReg(regNum)) {
169b1b19117SSaleem Abdulrasool co->setFloatReg(regNum, value);
170b1b19117SSaleem Abdulrasool return UNW_ESUCCESS;
171b1b19117SSaleem Abdulrasool }
172b1b19117SSaleem Abdulrasool return UNW_EBADREG;
173b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_set_fpreg,unw_set_fpreg)174e369a989SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_set_fpreg, unw_set_fpreg)
175b1b19117SSaleem Abdulrasool
176b1b19117SSaleem Abdulrasool /// Move cursor to next frame.
177e369a989SPetr Hosek _LIBUNWIND_HIDDEN int __unw_step(unw_cursor_t *cursor) {
178e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_step(cursor=%p)", static_cast<void *>(cursor));
179b1b19117SSaleem Abdulrasool AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
180b1b19117SSaleem Abdulrasool return co->step();
181b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_step,unw_step)182e369a989SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_step, unw_step)
183b1b19117SSaleem Abdulrasool
184b1b19117SSaleem Abdulrasool /// Get unwind info at cursor position in stack frame.
185e369a989SPetr Hosek _LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor,
186b1b19117SSaleem Abdulrasool unw_proc_info_t *info) {
187e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_get_proc_info(cursor=%p, &info=%p)",
188b1b19117SSaleem Abdulrasool static_cast<void *>(cursor), static_cast<void *>(info));
189b1b19117SSaleem Abdulrasool AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
190b1b19117SSaleem Abdulrasool co->getInfo(info);
191b1b19117SSaleem Abdulrasool if (info->end_ip == 0)
192b1b19117SSaleem Abdulrasool return UNW_ENOINFO;
193b1b19117SSaleem Abdulrasool return UNW_ESUCCESS;
194b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info,unw_get_proc_info)195e369a989SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info, unw_get_proc_info)
196b1b19117SSaleem Abdulrasool
197b1b19117SSaleem Abdulrasool /// Resume execution at cursor position (aka longjump).
198e369a989SPetr Hosek _LIBUNWIND_HIDDEN int __unw_resume(unw_cursor_t *cursor) {
199e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p)", static_cast<void *>(cursor));
200e03be2efSSaleem Abdulrasool #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
201adf1561dSShoaib Meenai // Inform the ASan runtime that now might be a good time to clean stuff up.
202adf1561dSShoaib Meenai __asan_handle_no_return();
203adf1561dSShoaib Meenai #endif
204b1b19117SSaleem Abdulrasool AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
205b1b19117SSaleem Abdulrasool co->jumpto();
206b1b19117SSaleem Abdulrasool return UNW_EUNSPEC;
207b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_resume,unw_resume)208e369a989SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_resume, unw_resume)
209b1b19117SSaleem Abdulrasool
210b1b19117SSaleem Abdulrasool /// Get name of function at cursor position in stack frame.
211e369a989SPetr Hosek _LIBUNWIND_HIDDEN int __unw_get_proc_name(unw_cursor_t *cursor, char *buf,
212b1b19117SSaleem Abdulrasool size_t bufLen, unw_word_t *offset) {
213e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)",
214b1b19117SSaleem Abdulrasool static_cast<void *>(cursor), static_cast<void *>(buf),
215b1b19117SSaleem Abdulrasool static_cast<unsigned long>(bufLen));
216b1b19117SSaleem Abdulrasool AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
217b1b19117SSaleem Abdulrasool if (co->getFunctionName(buf, bufLen, offset))
218b1b19117SSaleem Abdulrasool return UNW_ESUCCESS;
219b1b19117SSaleem Abdulrasool return UNW_EUNSPEC;
220b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_get_proc_name,unw_get_proc_name)221e369a989SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_name, unw_get_proc_name)
222b1b19117SSaleem Abdulrasool
223b1b19117SSaleem Abdulrasool /// Checks if a register is a floating-point register.
224e369a989SPetr Hosek _LIBUNWIND_HIDDEN int __unw_is_fpreg(unw_cursor_t *cursor,
225e369a989SPetr Hosek unw_regnum_t regNum) {
226e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_is_fpreg(cursor=%p, regNum=%d)",
227b1b19117SSaleem Abdulrasool static_cast<void *>(cursor), regNum);
228b1b19117SSaleem Abdulrasool AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
229b1b19117SSaleem Abdulrasool return co->validFloatReg(regNum);
230b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_is_fpreg,unw_is_fpreg)231e369a989SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_is_fpreg, unw_is_fpreg)
232b1b19117SSaleem Abdulrasool
233b1b19117SSaleem Abdulrasool /// Checks if a register is a floating-point register.
234e369a989SPetr Hosek _LIBUNWIND_HIDDEN const char *__unw_regname(unw_cursor_t *cursor,
235b1b19117SSaleem Abdulrasool unw_regnum_t regNum) {
236e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_regname(cursor=%p, regNum=%d)",
237b1b19117SSaleem Abdulrasool static_cast<void *>(cursor), regNum);
238b1b19117SSaleem Abdulrasool AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
239b1b19117SSaleem Abdulrasool return co->getRegisterName(regNum);
240b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_regname,unw_regname)241e369a989SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_regname, unw_regname)
242b1b19117SSaleem Abdulrasool
243b1b19117SSaleem Abdulrasool /// Checks if current frame is signal trampoline.
244e369a989SPetr Hosek _LIBUNWIND_HIDDEN int __unw_is_signal_frame(unw_cursor_t *cursor) {
245e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_is_signal_frame(cursor=%p)",
246b1b19117SSaleem Abdulrasool static_cast<void *>(cursor));
247b1b19117SSaleem Abdulrasool AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
248b1b19117SSaleem Abdulrasool return co->isSignalFrame();
249b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_is_signal_frame,unw_is_signal_frame)250e369a989SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_is_signal_frame, unw_is_signal_frame)
251b1b19117SSaleem Abdulrasool
252a85da649SXing Xue #ifdef _AIX
253a85da649SXing Xue _LIBUNWIND_EXPORT uintptr_t __unw_get_data_rel_base(unw_cursor_t *cursor) {
254a85da649SXing Xue _LIBUNWIND_TRACE_API("unw_get_data_rel_base(cursor=%p)",
255a85da649SXing Xue static_cast<void *>(cursor));
256a85da649SXing Xue AbstractUnwindCursor *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
257a85da649SXing Xue return co->getDataRelBase();
258a85da649SXing Xue }
_LIBUNWIND_WEAK_ALIAS(__unw_get_data_rel_base,unw_get_data_rel_base)259a85da649SXing Xue _LIBUNWIND_WEAK_ALIAS(__unw_get_data_rel_base, unw_get_data_rel_base)
260a85da649SXing Xue #endif
261a85da649SXing Xue
262b1b19117SSaleem Abdulrasool #ifdef __arm__
263b1b19117SSaleem Abdulrasool // Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD
264e369a989SPetr Hosek _LIBUNWIND_HIDDEN void __unw_save_vfp_as_X(unw_cursor_t *cursor) {
265e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_get_fpreg_save_vfp_as_X(cursor=%p)",
266b1b19117SSaleem Abdulrasool static_cast<void *>(cursor));
267b1b19117SSaleem Abdulrasool AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
268b1b19117SSaleem Abdulrasool return co->saveVFPAsX();
269b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_save_vfp_as_X,unw_save_vfp_as_X)2703aeb6585SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_save_vfp_as_X, unw_save_vfp_as_X)
271b1b19117SSaleem Abdulrasool #endif
272b1b19117SSaleem Abdulrasool
273b1b19117SSaleem Abdulrasool
2745808011bSRanjeet Singh #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
275c073b1baSEd Maste /// SPI: walks cached DWARF entries
276e369a989SPetr Hosek _LIBUNWIND_HIDDEN void __unw_iterate_dwarf_unwind_cache(void (*func)(
277b1b19117SSaleem Abdulrasool unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
278e369a989SPetr Hosek _LIBUNWIND_TRACE_API("__unw_iterate_dwarf_unwind_cache(func=%p)",
279b1b19117SSaleem Abdulrasool reinterpret_cast<void *>(func));
280b1b19117SSaleem Abdulrasool DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
281b1b19117SSaleem Abdulrasool }
_LIBUNWIND_WEAK_ALIAS(__unw_iterate_dwarf_unwind_cache,unw_iterate_dwarf_unwind_cache)282e369a989SPetr Hosek _LIBUNWIND_WEAK_ALIAS(__unw_iterate_dwarf_unwind_cache,
283e369a989SPetr Hosek unw_iterate_dwarf_unwind_cache)
284b1b19117SSaleem Abdulrasool
285b1b19117SSaleem Abdulrasool /// IPI: for __register_frame()
286e369a989SPetr Hosek void __unw_add_dynamic_fde(unw_word_t fde) {
287b1b19117SSaleem Abdulrasool CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
288b1b19117SSaleem Abdulrasool CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
289b1b19117SSaleem Abdulrasool const char *message = CFI_Parser<LocalAddressSpace>::decodeFDE(
290b1b19117SSaleem Abdulrasool LocalAddressSpace::sThisAddressSpace,
291b1b19117SSaleem Abdulrasool (LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo);
292b1b19117SSaleem Abdulrasool if (message == NULL) {
293b1b19117SSaleem Abdulrasool // dynamically registered FDEs don't have a mach_header group they are in.
294b1b19117SSaleem Abdulrasool // Use fde as mh_group
295b1b19117SSaleem Abdulrasool unw_word_t mh_group = fdeInfo.fdeStart;
296b1b19117SSaleem Abdulrasool DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group,
297b1b19117SSaleem Abdulrasool fdeInfo.pcStart, fdeInfo.pcEnd,
298b1b19117SSaleem Abdulrasool fdeInfo.fdeStart);
299b1b19117SSaleem Abdulrasool } else {
300e369a989SPetr Hosek _LIBUNWIND_DEBUG_LOG("__unw_add_dynamic_fde: bad fde: %s", message);
301b1b19117SSaleem Abdulrasool }
302b1b19117SSaleem Abdulrasool }
303b1b19117SSaleem Abdulrasool
304b1b19117SSaleem Abdulrasool /// IPI: for __deregister_frame()
__unw_remove_dynamic_fde(unw_word_t fde)305e369a989SPetr Hosek void __unw_remove_dynamic_fde(unw_word_t fde) {
306b1b19117SSaleem Abdulrasool // fde is own mh_group
307b1b19117SSaleem Abdulrasool DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
308b1b19117SSaleem Abdulrasool }
309bab39816SPeter S. Housel
__unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start)310bab39816SPeter S. Housel void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
311bab39816SPeter S. Housel // The eh_frame section start serves as the mh_group
312bab39816SPeter S. Housel unw_word_t mh_group = eh_frame_start;
313bab39816SPeter S. Housel CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
314bab39816SPeter S. Housel CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
315bab39816SPeter S. Housel auto p = (LocalAddressSpace::pint_t)eh_frame_start;
316bab39816SPeter S. Housel while (true) {
317bab39816SPeter S. Housel if (CFI_Parser<LocalAddressSpace>::decodeFDE(
318bab39816SPeter S. Housel LocalAddressSpace::sThisAddressSpace, p, &fdeInfo, &cieInfo,
319bab39816SPeter S. Housel true) == NULL) {
320bab39816SPeter S. Housel DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group,
321bab39816SPeter S. Housel fdeInfo.pcStart, fdeInfo.pcEnd,
322bab39816SPeter S. Housel fdeInfo.fdeStart);
323bab39816SPeter S. Housel p += fdeInfo.fdeLength;
324bab39816SPeter S. Housel } else if (CFI_Parser<LocalAddressSpace>::parseCIE(
325bab39816SPeter S. Housel LocalAddressSpace::sThisAddressSpace, p, &cieInfo) == NULL) {
326bab39816SPeter S. Housel p += cieInfo.cieLength;
327bab39816SPeter S. Housel } else
328bab39816SPeter S. Housel return;
329bab39816SPeter S. Housel }
330bab39816SPeter S. Housel }
331bab39816SPeter S. Housel
__unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start)332bab39816SPeter S. Housel void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
333bab39816SPeter S. Housel // The eh_frame section start serves as the mh_group
334bab39816SPeter S. Housel DwarfFDECache<LocalAddressSpace>::removeAllIn(
335bab39816SPeter S. Housel (LocalAddressSpace::pint_t)eh_frame_start);
336bab39816SPeter S. Housel }
337bab39816SPeter S. Housel
3385808011bSRanjeet Singh #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
339b51c49aaSMartin Storsjo #endif // !defined(__USING_SJLJ_EXCEPTIONS__)
340b1b19117SSaleem Abdulrasool
341b1b19117SSaleem Abdulrasool
342b1b19117SSaleem Abdulrasool
343b1b19117SSaleem Abdulrasool // Add logging hooks in Debug builds only
344b1b19117SSaleem Abdulrasool #ifndef NDEBUG
345b1b19117SSaleem Abdulrasool #include <stdlib.h>
346b1b19117SSaleem Abdulrasool
347b1b19117SSaleem Abdulrasool _LIBUNWIND_HIDDEN
logAPIs()348b1b19117SSaleem Abdulrasool bool logAPIs() {
349b1b19117SSaleem Abdulrasool // do manual lock to avoid use of _cxa_guard_acquire or initializers
350b1b19117SSaleem Abdulrasool static bool checked = false;
351b1b19117SSaleem Abdulrasool static bool log = false;
352b1b19117SSaleem Abdulrasool if (!checked) {
353b1b19117SSaleem Abdulrasool log = (getenv("LIBUNWIND_PRINT_APIS") != NULL);
354b1b19117SSaleem Abdulrasool checked = true;
355b1b19117SSaleem Abdulrasool }
356b1b19117SSaleem Abdulrasool return log;
357b1b19117SSaleem Abdulrasool }
358b1b19117SSaleem Abdulrasool
359b1b19117SSaleem Abdulrasool _LIBUNWIND_HIDDEN
logUnwinding()360b1b19117SSaleem Abdulrasool bool logUnwinding() {
361b1b19117SSaleem Abdulrasool // do manual lock to avoid use of _cxa_guard_acquire or initializers
362b1b19117SSaleem Abdulrasool static bool checked = false;
363b1b19117SSaleem Abdulrasool static bool log = false;
364b1b19117SSaleem Abdulrasool if (!checked) {
365b1b19117SSaleem Abdulrasool log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL);
366b1b19117SSaleem Abdulrasool checked = true;
367b1b19117SSaleem Abdulrasool }
368b1b19117SSaleem Abdulrasool return log;
369b1b19117SSaleem Abdulrasool }
370b1b19117SSaleem Abdulrasool
371c06f0cf8SSaleem Abdulrasool _LIBUNWIND_HIDDEN
logDWARF()372c06f0cf8SSaleem Abdulrasool bool logDWARF() {
373c06f0cf8SSaleem Abdulrasool // do manual lock to avoid use of _cxa_guard_acquire or initializers
374c06f0cf8SSaleem Abdulrasool static bool checked = false;
375c06f0cf8SSaleem Abdulrasool static bool log = false;
376c06f0cf8SSaleem Abdulrasool if (!checked) {
377c06f0cf8SSaleem Abdulrasool log = (getenv("LIBUNWIND_PRINT_DWARF") != NULL);
378c06f0cf8SSaleem Abdulrasool checked = true;
379c06f0cf8SSaleem Abdulrasool }
380c06f0cf8SSaleem Abdulrasool return log;
381c06f0cf8SSaleem Abdulrasool }
382c06f0cf8SSaleem Abdulrasool
383b1b19117SSaleem Abdulrasool #endif // NDEBUG
384b1b19117SSaleem Abdulrasool
385