1 //===--------------------------- libunwind.cpp ----------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 // Implements unw_* functions from <libunwind.h>
10 //===----------------------------------------------------------------------===//
12 #include <libunwind.h>
14 #include "libunwind_ext.h"
20 #if !defined(__USING_SJLJ_EXCEPTIONS__)
21 #include "AddressSpace.hpp"
22 #include "UnwindCursor.hpp"
24 using namespace libunwind
;
26 /// internal object to represent this processes address space
27 LocalAddressSpace
LocalAddressSpace::sThisAddressSpace
;
29 _LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space
=
30 (unw_addr_space_t
)&LocalAddressSpace::sThisAddressSpace
;
32 /// Create a cursor of a thread in this process given 'context' recorded by
33 /// __unw_getcontext().
34 _LIBUNWIND_HIDDEN
int __unw_init_local(unw_cursor_t
*cursor
,
35 unw_context_t
*context
) {
36 _LIBUNWIND_TRACE_API("__unw_init_local(cursor=%p, context=%p)",
37 static_cast<void *>(cursor
),
38 static_cast<void *>(context
));
40 # define REGISTER_KIND Registers_x86
41 #elif defined(__x86_64__)
42 # define REGISTER_KIND Registers_x86_64
43 #elif defined(__powerpc64__)
44 # define REGISTER_KIND Registers_ppc64
45 #elif defined(__ppc__)
46 # define REGISTER_KIND Registers_ppc
47 #elif defined(__aarch64__)
48 # define REGISTER_KIND Registers_arm64
49 #elif defined(__arm__)
50 # define REGISTER_KIND Registers_arm
51 #elif defined(__or1k__)
52 # define REGISTER_KIND Registers_or1k
53 #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
54 # define REGISTER_KIND Registers_mips_o32
55 #elif defined(__mips64)
56 # define REGISTER_KIND Registers_mips_newabi
57 #elif defined(__mips__)
58 # warning The MIPS architecture is not supported with this ABI and environment!
59 #elif defined(__sparc__)
60 # define REGISTER_KIND Registers_sparc
61 #elif defined(__riscv) && __riscv_xlen == 64
62 # define REGISTER_KIND Registers_riscv
64 # error Architecture not supported
66 // Use "placement new" to allocate UnwindCursor in the cursor buffer.
67 new (reinterpret_cast<UnwindCursor
<LocalAddressSpace
, REGISTER_KIND
> *>(cursor
))
68 UnwindCursor
<LocalAddressSpace
, REGISTER_KIND
>(
69 context
, LocalAddressSpace::sThisAddressSpace
);
71 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
72 co
->setInfoBasedOnIPRegister();
76 _LIBUNWIND_WEAK_ALIAS(__unw_init_local
, unw_init_local
)
78 /// Get value of specified register at cursor position in stack frame.
79 _LIBUNWIND_HIDDEN
int __unw_get_reg(unw_cursor_t
*cursor
, unw_regnum_t regNum
,
81 _LIBUNWIND_TRACE_API("__unw_get_reg(cursor=%p, regNum=%d, &value=%p)",
82 static_cast<void *>(cursor
), regNum
,
83 static_cast<void *>(value
));
84 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
85 if (co
->validReg(regNum
)) {
86 *value
= co
->getReg(regNum
);
91 _LIBUNWIND_WEAK_ALIAS(__unw_get_reg
, unw_get_reg
)
93 /// Set value of specified register at cursor position in stack frame.
94 _LIBUNWIND_HIDDEN
int __unw_set_reg(unw_cursor_t
*cursor
, unw_regnum_t regNum
,
96 _LIBUNWIND_TRACE_API("__unw_set_reg(cursor=%p, regNum=%d, value=0x%" PRIxPTR
98 static_cast<void *>(cursor
), regNum
, value
);
99 typedef LocalAddressSpace::pint_t pint_t
;
100 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
101 if (co
->validReg(regNum
)) {
102 co
->setReg(regNum
, (pint_t
)value
);
103 // specical case altering IP to re-find info (being called by personality
105 if (regNum
== UNW_REG_IP
) {
106 unw_proc_info_t info
;
107 // First, get the FDE for the old location and then update it.
109 co
->setInfoBasedOnIPRegister(false);
110 // If the original call expects stack adjustment, perform this now.
111 // Normal frame unwinding would have included the offset already in the
113 // Note: for PA-RISC and other platforms where the stack grows up,
114 // this should actually be - info.gp. LLVM doesn't currently support
115 // any such platforms and Clang doesn't export a macro for them.
117 co
->setReg(UNW_REG_SP
, co
->getReg(UNW_REG_SP
) + info
.gp
);
123 _LIBUNWIND_WEAK_ALIAS(__unw_set_reg
, unw_set_reg
)
125 /// Get value of specified float register at cursor position in stack frame.
126 _LIBUNWIND_HIDDEN
int __unw_get_fpreg(unw_cursor_t
*cursor
, unw_regnum_t regNum
,
127 unw_fpreg_t
*value
) {
128 _LIBUNWIND_TRACE_API("__unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)",
129 static_cast<void *>(cursor
), regNum
,
130 static_cast<void *>(value
));
131 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
132 if (co
->validFloatReg(regNum
)) {
133 *value
= co
->getFloatReg(regNum
);
138 _LIBUNWIND_WEAK_ALIAS(__unw_get_fpreg
, unw_get_fpreg
)
140 /// Set value of specified float register at cursor position in stack frame.
141 _LIBUNWIND_HIDDEN
int __unw_set_fpreg(unw_cursor_t
*cursor
, unw_regnum_t regNum
,
143 #if defined(_LIBUNWIND_ARM_EHABI)
144 _LIBUNWIND_TRACE_API("__unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)",
145 static_cast<void *>(cursor
), regNum
, value
);
147 _LIBUNWIND_TRACE_API("__unw_set_fpreg(cursor=%p, regNum=%d, value=%g)",
148 static_cast<void *>(cursor
), regNum
, value
);
150 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
151 if (co
->validFloatReg(regNum
)) {
152 co
->setFloatReg(regNum
, value
);
157 _LIBUNWIND_WEAK_ALIAS(__unw_set_fpreg
, unw_set_fpreg
)
159 /// Move cursor to next frame.
160 _LIBUNWIND_HIDDEN
int __unw_step(unw_cursor_t
*cursor
) {
161 _LIBUNWIND_TRACE_API("__unw_step(cursor=%p)", static_cast<void *>(cursor
));
162 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
165 _LIBUNWIND_WEAK_ALIAS(__unw_step
, unw_step
)
167 /// Get unwind info at cursor position in stack frame.
168 _LIBUNWIND_HIDDEN
int __unw_get_proc_info(unw_cursor_t
*cursor
,
169 unw_proc_info_t
*info
) {
170 _LIBUNWIND_TRACE_API("__unw_get_proc_info(cursor=%p, &info=%p)",
171 static_cast<void *>(cursor
), static_cast<void *>(info
));
172 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
174 if (info
->end_ip
== 0)
178 _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info
, unw_get_proc_info
)
180 /// Resume execution at cursor position (aka longjump).
181 _LIBUNWIND_HIDDEN
int __unw_resume(unw_cursor_t
*cursor
) {
182 _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p)", static_cast<void *>(cursor
));
183 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
187 _LIBUNWIND_WEAK_ALIAS(__unw_resume
, unw_resume
)
189 /// Get name of function at cursor position in stack frame.
190 _LIBUNWIND_HIDDEN
int __unw_get_proc_name(unw_cursor_t
*cursor
, char *buf
,
191 size_t bufLen
, unw_word_t
*offset
) {
192 _LIBUNWIND_TRACE_API("__unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)",
193 static_cast<void *>(cursor
), static_cast<void *>(buf
),
194 static_cast<unsigned long>(bufLen
));
195 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
196 if (co
->getFunctionName(buf
, bufLen
, offset
))
200 _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_name
, unw_get_proc_name
)
202 /// Checks if a register is a floating-point register.
203 _LIBUNWIND_HIDDEN
int __unw_is_fpreg(unw_cursor_t
*cursor
,
204 unw_regnum_t regNum
) {
205 _LIBUNWIND_TRACE_API("__unw_is_fpreg(cursor=%p, regNum=%d)",
206 static_cast<void *>(cursor
), regNum
);
207 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
208 return co
->validFloatReg(regNum
);
210 _LIBUNWIND_WEAK_ALIAS(__unw_is_fpreg
, unw_is_fpreg
)
212 /// Checks if a register is a floating-point register.
213 _LIBUNWIND_HIDDEN
const char *__unw_regname(unw_cursor_t
*cursor
,
214 unw_regnum_t regNum
) {
215 _LIBUNWIND_TRACE_API("__unw_regname(cursor=%p, regNum=%d)",
216 static_cast<void *>(cursor
), regNum
);
217 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
218 return co
->getRegisterName(regNum
);
220 _LIBUNWIND_WEAK_ALIAS(__unw_regname
, unw_regname
)
222 /// Checks if current frame is signal trampoline.
223 _LIBUNWIND_HIDDEN
int __unw_is_signal_frame(unw_cursor_t
*cursor
) {
224 _LIBUNWIND_TRACE_API("__unw_is_signal_frame(cursor=%p)",
225 static_cast<void *>(cursor
));
226 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
227 return co
->isSignalFrame();
229 _LIBUNWIND_WEAK_ALIAS(__unw_is_signal_frame
, unw_is_signal_frame
)
232 // Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD
233 _LIBUNWIND_HIDDEN
void __unw_save_vfp_as_X(unw_cursor_t
*cursor
) {
234 _LIBUNWIND_TRACE_API("__unw_get_fpreg_save_vfp_as_X(cursor=%p)",
235 static_cast<void *>(cursor
));
236 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
237 return co
->saveVFPAsX();
239 _LIBUNWIND_WEAK_ALIAS(__unw_save_vfp_as_X
, unw_save_vfp_as_X
)
243 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
244 /// SPI: walks cached DWARF entries
245 _LIBUNWIND_HIDDEN
void __unw_iterate_dwarf_unwind_cache(void (*func
)(
246 unw_word_t ip_start
, unw_word_t ip_end
, unw_word_t fde
, unw_word_t mh
)) {
247 _LIBUNWIND_TRACE_API("__unw_iterate_dwarf_unwind_cache(func=%p)",
248 reinterpret_cast<void *>(func
));
249 DwarfFDECache
<LocalAddressSpace
>::iterateCacheEntries(func
);
251 _LIBUNWIND_WEAK_ALIAS(__unw_iterate_dwarf_unwind_cache
,
252 unw_iterate_dwarf_unwind_cache
)
254 /// IPI: for __register_frame()
255 void __unw_add_dynamic_fde(unw_word_t fde
) {
256 CFI_Parser
<LocalAddressSpace
>::FDE_Info fdeInfo
;
257 CFI_Parser
<LocalAddressSpace
>::CIE_Info cieInfo
;
258 const char *message
= CFI_Parser
<LocalAddressSpace
>::decodeFDE(
259 LocalAddressSpace::sThisAddressSpace
,
260 (LocalAddressSpace::pint_t
) fde
, &fdeInfo
, &cieInfo
);
261 if (message
== NULL
) {
262 // dynamically registered FDEs don't have a mach_header group they are in.
263 // Use fde as mh_group
264 unw_word_t mh_group
= fdeInfo
.fdeStart
;
265 DwarfFDECache
<LocalAddressSpace
>::add((LocalAddressSpace::pint_t
)mh_group
,
266 fdeInfo
.pcStart
, fdeInfo
.pcEnd
,
269 _LIBUNWIND_DEBUG_LOG("__unw_add_dynamic_fde: bad fde: %s", message
);
273 /// IPI: for __deregister_frame()
274 void __unw_remove_dynamic_fde(unw_word_t fde
) {
275 // fde is own mh_group
276 DwarfFDECache
<LocalAddressSpace
>::removeAllIn((LocalAddressSpace::pint_t
)fde
);
278 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
279 #endif // !defined(__USING_SJLJ_EXCEPTIONS__)
283 // Add logging hooks in Debug builds only
289 // do manual lock to avoid use of _cxa_guard_acquire or initializers
290 static bool checked
= false;
291 static bool log
= false;
293 log
= (getenv("LIBUNWIND_PRINT_APIS") != NULL
);
300 bool logUnwinding() {
301 // do manual lock to avoid use of _cxa_guard_acquire or initializers
302 static bool checked
= false;
303 static bool log
= false;
305 log
= (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL
);
313 // do manual lock to avoid use of _cxa_guard_acquire or initializers
314 static bool checked
= false;
315 static bool log
= false;
317 log
= (getenv("LIBUNWIND_PRINT_DWARF") != NULL
);