blob: 8267b9e7cdcef4cbd9d2d7823cbcf24d277c55bb [file] [log] [blame]
Ed Maste6f723382016-08-30 13:08:21 +00001//===--------------------------- libunwind.cpp ----------------------------===//
Saleem Abdulrasool17552662015-04-24 19:39:17 +00002//
Chandler Carruth61860a52019-01-19 10:56:40 +00003// 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
Saleem Abdulrasool17552662015-04-24 19:39:17 +00006//
7//
8// Implements unw_* functions from <libunwind.h>
9//
10//===----------------------------------------------------------------------===//
11
12#include <libunwind.h>
13
14#ifndef NDEBUG
15#include <cstdlib> // getenv
16#endif
17#include <new>
Saleem Abdulrasoole1539392015-05-11 16:35:13 +000018#include <algorithm>
Saleem Abdulrasool17552662015-04-24 19:39:17 +000019
20#include "libunwind_ext.h"
21#include "config.h"
22
23#include <stdlib.h>
24
25
Martin Storsjo9f16c6c2017-09-26 08:07:26 +000026#if !defined(__USING_SJLJ_EXCEPTIONS__)
Ed Schoutenedb76802017-03-09 08:04:07 +000027#include "AddressSpace.hpp"
Saleem Abdulrasool17552662015-04-24 19:39:17 +000028#include "UnwindCursor.hpp"
29
30using namespace libunwind;
31
32/// internal object to represent this processes address space
33LocalAddressSpace LocalAddressSpace::sThisAddressSpace;
34
35_LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space =
36 (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace;
37
38/// record the registers and stack position of the caller
39extern int unw_getcontext(unw_context_t *);
40// note: unw_getcontext() implemented in assembly
41
42/// Create a cursor of a thread in this process given 'context' recorded by
43/// unw_getcontext().
44_LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
45 unw_context_t *context) {
Ed Maste41bc5a72016-08-30 15:38:10 +000046 _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)",
Saleem Abdulrasool17552662015-04-24 19:39:17 +000047 static_cast<void *>(cursor),
48 static_cast<void *>(context));
Saleem Abdulrasool17552662015-04-24 19:39:17 +000049#if defined(__i386__)
Asiri Rathnayakec00dcef2016-05-25 12:36:34 +000050# define REGISTER_KIND Registers_x86
Saleem Abdulrasool17552662015-04-24 19:39:17 +000051#elif defined(__x86_64__)
Asiri Rathnayakec00dcef2016-05-25 12:36:34 +000052# define REGISTER_KIND Registers_x86_64
Martin Storsjo8338b0a2018-01-02 22:11:30 +000053#elif defined(__powerpc64__)
54# define REGISTER_KIND Registers_ppc64
Saleem Abdulrasool17552662015-04-24 19:39:17 +000055#elif defined(__ppc__)
Asiri Rathnayakec00dcef2016-05-25 12:36:34 +000056# define REGISTER_KIND Registers_ppc
57#elif defined(__aarch64__)
58# define REGISTER_KIND Registers_arm64
Martin Storsjoa72285f2017-11-02 08:16:16 +000059#elif defined(__arm__)
Asiri Rathnayakec00dcef2016-05-25 12:36:34 +000060# define REGISTER_KIND Registers_arm
Peter Zotov8d639992015-08-31 05:26:37 +000061#elif defined(__or1k__)
Asiri Rathnayakec00dcef2016-05-25 12:36:34 +000062# define REGISTER_KIND Registers_or1k
John Baldwin40300292018-05-15 22:44:56 +000063#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
John Baldwin56441d42017-12-12 21:43:36 +000064# define REGISTER_KIND Registers_mips_o32
John Baldwin40300292018-05-15 22:44:56 +000065#elif defined(__mips64)
John Baldwin541a4352018-01-09 17:07:18 +000066# define REGISTER_KIND Registers_mips_newabi
Vasileios Kalintiris3bd271c2015-09-26 18:26:01 +000067#elif defined(__mips__)
John Baldwin56441d42017-12-12 21:43:36 +000068# warning The MIPS architecture is not supported with this ABI and environment!
Daniel Cederman9f2f07a2019-01-14 10:15:20 +000069#elif defined(__sparc__)
70# define REGISTER_KIND Registers_sparc
Ed Maste846892c2015-08-13 14:21:03 +000071#else
Asiri Rathnayakec00dcef2016-05-25 12:36:34 +000072# error Architecture not supported
Saleem Abdulrasool17552662015-04-24 19:39:17 +000073#endif
Asiri Rathnayakec00dcef2016-05-25 12:36:34 +000074 // Use "placement new" to allocate UnwindCursor in the cursor buffer.
75 new ((void *)cursor) UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
76 context, LocalAddressSpace::sThisAddressSpace);
77#undef REGISTER_KIND
Saleem Abdulrasool17552662015-04-24 19:39:17 +000078 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
79 co->setInfoBasedOnIPRegister();
80
81 return UNW_ESUCCESS;
82}
83
84#ifdef UNW_REMOTE
85/// Create a cursor into a thread in another process.
86_LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor,
87 unw_addr_space_t as,
88 void *arg) {
89 // special case: unw_init_remote(xx, unw_local_addr_space, xx)
90 if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace)
91 return unw_init_local(cursor, NULL); //FIXME
92
93 // use "placement new" to allocate UnwindCursor in the cursor buffer
94 switch (as->cpuType) {
95 case CPU_TYPE_I386:
96 new ((void *)cursor)
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +000097 UnwindCursor<RemoteAddressSpace<Pointer32<LittleEndian>>,
Saleem Abdulrasool17552662015-04-24 19:39:17 +000098 Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg);
99 break;
100 case CPU_TYPE_X86_64:
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000101 new ((void *)cursor)
102 UnwindCursor<RemoteAddressSpace<Pointer64<LittleEndian>>,
103 Registers_x86_64>(((unw_addr_space_x86_64 *)as)->oas, arg);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000104 break;
105 case CPU_TYPE_POWERPC:
106 new ((void *)cursor)
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000107 UnwindCursor<RemoteAddressSpace<Pointer32<BigEndian>>,
108 Registers_ppc>(((unw_addr_space_ppc *)as)->oas, arg);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000109 break;
110 default:
111 return UNW_EUNSPEC;
112 }
113 return UNW_ESUCCESS;
114}
115
116
117static bool is64bit(task_t task) {
118 return false; // FIXME
119}
120
121/// Create an address_space object for use in examining another task.
122_LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) {
123#if __i386__
124 if (is64bit(task)) {
125 unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task);
126 as->taskPort = task;
127 as->cpuType = CPU_TYPE_X86_64;
128 //as->oas
129 } else {
130 unw_addr_space_i386 *as = new unw_addr_space_i386(task);
131 as->taskPort = task;
132 as->cpuType = CPU_TYPE_I386;
133 //as->oas
134 }
135#else
136// FIXME
137#endif
138}
139
140
141/// Delete an address_space object.
142_LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) {
143 switch (asp->cpuType) {
144#if __i386__ || __x86_64__
145 case CPU_TYPE_I386: {
146 unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp;
147 delete as;
148 }
149 break;
150 case CPU_TYPE_X86_64: {
151 unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp;
152 delete as;
153 }
154 break;
155#endif
156 case CPU_TYPE_POWERPC: {
157 unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp;
158 delete as;
159 }
160 break;
161 }
162}
163#endif // UNW_REMOTE
164
165
166/// Get value of specified register at cursor position in stack frame.
167_LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
168 unw_word_t *value) {
Ed Maste41bc5a72016-08-30 15:38:10 +0000169 _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)",
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000170 static_cast<void *>(cursor), regNum,
171 static_cast<void *>(value));
172 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
173 if (co->validReg(regNum)) {
174 *value = co->getReg(regNum);
175 return UNW_ESUCCESS;
176 }
177 return UNW_EBADREG;
178}
179
180
181/// Set value of specified register at cursor position in stack frame.
182_LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
183 unw_word_t value) {
Martin Storsjo97e2d982017-10-30 19:06:34 +0000184 _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%" PRIxPTR ")",
185 static_cast<void *>(cursor), regNum, value);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000186 typedef LocalAddressSpace::pint_t pint_t;
187 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
188 if (co->validReg(regNum)) {
189 co->setReg(regNum, (pint_t)value);
190 // specical case altering IP to re-find info (being called by personality
191 // function)
Joerg Sonnenberger7ac54d32018-07-17 19:00:51 +0000192 if (regNum == UNW_REG_IP) {
193 unw_proc_info_t info;
194 // First, get the FDE for the old location and then update it.
195 co->getInfo(&info);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000196 co->setInfoBasedOnIPRegister(false);
Joerg Sonnenberger7ac54d32018-07-17 19:00:51 +0000197 // If the original call expects stack adjustment, perform this now.
198 // Normal frame unwinding would have included the offset already in the
199 // CFA computation.
200 // Note: for PA-RISC and other platforms where the stack grows up,
201 // this should actually be - info.gp. LLVM doesn't currently support
202 // any such platforms and Clang doesn't export a macro for them.
203 if (info.gp)
204 co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp);
205 }
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000206 return UNW_ESUCCESS;
207 }
208 return UNW_EBADREG;
209}
210
211
212/// Get value of specified float register at cursor position in stack frame.
213_LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
214 unw_fpreg_t *value) {
Ed Maste41bc5a72016-08-30 15:38:10 +0000215 _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)",
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000216 static_cast<void *>(cursor), regNum,
217 static_cast<void *>(value));
218 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
219 if (co->validFloatReg(regNum)) {
220 *value = co->getFloatReg(regNum);
221 return UNW_ESUCCESS;
222 }
223 return UNW_EBADREG;
224}
225
226
227/// Set value of specified float register at cursor position in stack frame.
228_LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
229 unw_fpreg_t value) {
Ranjeet Singh421231a2017-03-31 15:28:06 +0000230#if defined(_LIBUNWIND_ARM_EHABI)
Ed Maste41bc5a72016-08-30 15:38:10 +0000231 _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)",
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000232 static_cast<void *>(cursor), regNum, value);
233#else
Ed Maste41bc5a72016-08-30 15:38:10 +0000234 _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)",
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000235 static_cast<void *>(cursor), regNum, value);
236#endif
237 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
238 if (co->validFloatReg(regNum)) {
239 co->setFloatReg(regNum, value);
240 return UNW_ESUCCESS;
241 }
242 return UNW_EBADREG;
243}
244
245
246/// Move cursor to next frame.
247_LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) {
Ed Maste41bc5a72016-08-30 15:38:10 +0000248 _LIBUNWIND_TRACE_API("unw_step(cursor=%p)", static_cast<void *>(cursor));
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000249 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
250 return co->step();
251}
252
253
254/// Get unwind info at cursor position in stack frame.
255_LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor,
256 unw_proc_info_t *info) {
Ed Maste41bc5a72016-08-30 15:38:10 +0000257 _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)",
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000258 static_cast<void *>(cursor), static_cast<void *>(info));
259 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
260 co->getInfo(info);
261 if (info->end_ip == 0)
262 return UNW_ENOINFO;
263 else
264 return UNW_ESUCCESS;
265}
266
267
268/// Resume execution at cursor position (aka longjump).
269_LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) {
Ed Maste41bc5a72016-08-30 15:38:10 +0000270 _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)", static_cast<void *>(cursor));
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000271 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
272 co->jumpto();
273 return UNW_EUNSPEC;
274}
275
276
277/// Get name of function at cursor position in stack frame.
278_LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf,
279 size_t bufLen, unw_word_t *offset) {
Ed Maste41bc5a72016-08-30 15:38:10 +0000280 _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)",
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000281 static_cast<void *>(cursor), static_cast<void *>(buf),
282 static_cast<unsigned long>(bufLen));
283 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
284 if (co->getFunctionName(buf, bufLen, offset))
285 return UNW_ESUCCESS;
286 else
287 return UNW_EUNSPEC;
288}
289
290
291/// Checks if a register is a floating-point register.
292_LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) {
Ed Maste41bc5a72016-08-30 15:38:10 +0000293 _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)",
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000294 static_cast<void *>(cursor), regNum);
295 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
296 return co->validFloatReg(regNum);
297}
298
299
300/// Checks if a register is a floating-point register.
301_LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor,
302 unw_regnum_t regNum) {
Ed Maste41bc5a72016-08-30 15:38:10 +0000303 _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)",
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000304 static_cast<void *>(cursor), regNum);
305 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
306 return co->getRegisterName(regNum);
307}
308
309
310/// Checks if current frame is signal trampoline.
311_LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) {
Ed Maste41bc5a72016-08-30 15:38:10 +0000312 _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)",
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000313 static_cast<void *>(cursor));
314 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
315 return co->isSignalFrame();
316}
317
318#ifdef __arm__
319// Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD
320_LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) {
Ed Maste41bc5a72016-08-30 15:38:10 +0000321 _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)",
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000322 static_cast<void *>(cursor));
323 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
324 return co->saveVFPAsX();
325}
326#endif
327
328
Ranjeet Singh421231a2017-03-31 15:28:06 +0000329#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Ed Maste4c43c3d2016-07-19 17:15:50 +0000330/// SPI: walks cached DWARF entries
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000331_LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)(
332 unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
Ed Maste41bc5a72016-08-30 15:38:10 +0000333 _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)",
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000334 reinterpret_cast<void *>(func));
335 DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
336}
337
338
339/// IPI: for __register_frame()
340void _unw_add_dynamic_fde(unw_word_t fde) {
341 CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
342 CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
343 const char *message = CFI_Parser<LocalAddressSpace>::decodeFDE(
344 LocalAddressSpace::sThisAddressSpace,
345 (LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo);
346 if (message == NULL) {
347 // dynamically registered FDEs don't have a mach_header group they are in.
348 // Use fde as mh_group
349 unw_word_t mh_group = fdeInfo.fdeStart;
350 DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group,
351 fdeInfo.pcStart, fdeInfo.pcEnd,
352 fdeInfo.fdeStart);
353 } else {
354 _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message);
355 }
356}
357
358/// IPI: for __deregister_frame()
359void _unw_remove_dynamic_fde(unw_word_t fde) {
360 // fde is own mh_group
361 DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
362}
Ranjeet Singh421231a2017-03-31 15:28:06 +0000363#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Martin Storsjo9f16c6c2017-09-26 08:07:26 +0000364#endif // !defined(__USING_SJLJ_EXCEPTIONS__)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000365
366
367
368// Add logging hooks in Debug builds only
369#ifndef NDEBUG
370#include <stdlib.h>
371
372_LIBUNWIND_HIDDEN
373bool logAPIs() {
374 // do manual lock to avoid use of _cxa_guard_acquire or initializers
375 static bool checked = false;
376 static bool log = false;
377 if (!checked) {
378 log = (getenv("LIBUNWIND_PRINT_APIS") != NULL);
379 checked = true;
380 }
381 return log;
382}
383
384_LIBUNWIND_HIDDEN
385bool logUnwinding() {
386 // do manual lock to avoid use of _cxa_guard_acquire or initializers
387 static bool checked = false;
388 static bool log = false;
389 if (!checked) {
390 log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL);
391 checked = true;
392 }
393 return log;
394}
395
Saleem Abdulrasoold1be5b02017-01-21 16:22:57 +0000396_LIBUNWIND_HIDDEN
397bool logDWARF() {
398 // do manual lock to avoid use of _cxa_guard_acquire or initializers
399 static bool checked = false;
400 static bool log = false;
401 if (!checked) {
402 log = (getenv("LIBUNWIND_PRINT_DWARF") != NULL);
403 checked = true;
404 }
405 return log;
406}
407
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000408#endif // NDEBUG
409