blob: c7318fb7cce74ab25c78fff4b85dac80d9051691 [file] [log] [blame]
Ed Maste17473fd2016-08-30 13:08:21 +00001//===--------------------------- libunwind.cpp ----------------------------===//
Saleem Abdulrasool675df582015-04-24 19:39:17 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Implements unw_* functions from <libunwind.h>
10//
11//===----------------------------------------------------------------------===//
12
13#include <libunwind.h>
14
15#ifndef NDEBUG
16#include <cstdlib> // getenv
17#endif
18#include <new>
Saleem Abdulrasoola802ef42015-05-11 16:35:13 +000019#include <algorithm>
Saleem Abdulrasool675df582015-04-24 19:39:17 +000020
21#include "libunwind_ext.h"
22#include "config.h"
23
24#include <stdlib.h>
25
26
Martin Storsjoe53dc3f2017-09-26 08:07:26 +000027#if !defined(__USING_SJLJ_EXCEPTIONS__)
Ed Schouten188f3c72017-03-09 08:04:07 +000028#include "AddressSpace.hpp"
Saleem Abdulrasool675df582015-04-24 19:39:17 +000029#include "UnwindCursor.hpp"
30
31using namespace libunwind;
32
33/// internal object to represent this processes address space
34LocalAddressSpace LocalAddressSpace::sThisAddressSpace;
35
36_LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space =
37 (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace;
38
39/// record the registers and stack position of the caller
40extern int unw_getcontext(unw_context_t *);
41// note: unw_getcontext() implemented in assembly
42
43/// Create a cursor of a thread in this process given 'context' recorded by
44/// unw_getcontext().
45_LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
46 unw_context_t *context) {
Ed Masteadc29082016-08-30 15:38:10 +000047 _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +000048 static_cast<void *>(cursor),
49 static_cast<void *>(context));
Saleem Abdulrasool675df582015-04-24 19:39:17 +000050#if defined(__i386__)
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000051# define REGISTER_KIND Registers_x86
Saleem Abdulrasool675df582015-04-24 19:39:17 +000052#elif defined(__x86_64__)
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000053# define REGISTER_KIND Registers_x86_64
Martin Storsjodc25db12018-01-02 22:11:30 +000054#elif defined(__powerpc64__)
55# define REGISTER_KIND Registers_ppc64
Saleem Abdulrasool675df582015-04-24 19:39:17 +000056#elif defined(__ppc__)
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000057# define REGISTER_KIND Registers_ppc
58#elif defined(__aarch64__)
59# define REGISTER_KIND Registers_arm64
Martin Storsjo23a943b2017-11-02 08:16:16 +000060#elif defined(__arm__)
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000061# define REGISTER_KIND Registers_arm
Peter Zotovd4255ab2015-08-31 05:26:37 +000062#elif defined(__or1k__)
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000063# define REGISTER_KIND Registers_or1k
John Baldwind550d632018-02-27 21:24:02 +000064#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 && \
65 defined(__mips_soft_float)
John Baldwin375a3662017-12-12 21:43:36 +000066# define REGISTER_KIND Registers_mips_o32
John Baldwind550d632018-02-27 21:24:02 +000067#elif defined(__mips64) && defined(__mips_soft_float)
John Baldwinda0af182018-01-09 17:07:18 +000068# define REGISTER_KIND Registers_mips_newabi
Vasileios Kalintirisdb1c2632015-09-26 18:26:01 +000069#elif defined(__mips__)
John Baldwin375a3662017-12-12 21:43:36 +000070# warning The MIPS architecture is not supported with this ABI and environment!
Ed Maste40377de2015-08-13 14:21:03 +000071#else
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000072# error Architecture not supported
Saleem Abdulrasool675df582015-04-24 19:39:17 +000073#endif
Asiri Rathnayaked2d1ea92016-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 Abdulrasool675df582015-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 Abdulrasoolfa054682017-01-21 16:22:46 +000097 UnwindCursor<RemoteAddressSpace<Pointer32<LittleEndian>>,
Saleem Abdulrasool675df582015-04-24 19:39:17 +000098 Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg);
99 break;
100 case CPU_TYPE_X86_64:
Saleem Abdulrasoolfa054682017-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 Abdulrasool675df582015-04-24 19:39:17 +0000104 break;
105 case CPU_TYPE_POWERPC:
106 new ((void *)cursor)
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000107 UnwindCursor<RemoteAddressSpace<Pointer32<BigEndian>>,
108 Registers_ppc>(((unw_addr_space_ppc *)as)->oas, arg);
Saleem Abdulrasool675df582015-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 Masteadc29082016-08-30 15:38:10 +0000169 _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)",
Saleem Abdulrasool675df582015-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 Storsjo85f4cfd2017-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 Abdulrasool675df582015-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)
192 if (regNum == UNW_REG_IP)
193 co->setInfoBasedOnIPRegister(false);
194 return UNW_ESUCCESS;
195 }
196 return UNW_EBADREG;
197}
198
199
200/// Get value of specified float register at cursor position in stack frame.
201_LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
202 unw_fpreg_t *value) {
Ed Masteadc29082016-08-30 15:38:10 +0000203 _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000204 static_cast<void *>(cursor), regNum,
205 static_cast<void *>(value));
206 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
207 if (co->validFloatReg(regNum)) {
208 *value = co->getFloatReg(regNum);
209 return UNW_ESUCCESS;
210 }
211 return UNW_EBADREG;
212}
213
214
215/// Set value of specified float register at cursor position in stack frame.
216_LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
217 unw_fpreg_t value) {
Ranjeet Singh7d674132017-03-31 15:28:06 +0000218#if defined(_LIBUNWIND_ARM_EHABI)
Ed Masteadc29082016-08-30 15:38:10 +0000219 _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000220 static_cast<void *>(cursor), regNum, value);
221#else
Ed Masteadc29082016-08-30 15:38:10 +0000222 _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000223 static_cast<void *>(cursor), regNum, value);
224#endif
225 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
226 if (co->validFloatReg(regNum)) {
227 co->setFloatReg(regNum, value);
228 return UNW_ESUCCESS;
229 }
230 return UNW_EBADREG;
231}
232
233
234/// Move cursor to next frame.
235_LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) {
Ed Masteadc29082016-08-30 15:38:10 +0000236 _LIBUNWIND_TRACE_API("unw_step(cursor=%p)", static_cast<void *>(cursor));
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000237 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
238 return co->step();
239}
240
241
242/// Get unwind info at cursor position in stack frame.
243_LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor,
244 unw_proc_info_t *info) {
Ed Masteadc29082016-08-30 15:38:10 +0000245 _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000246 static_cast<void *>(cursor), static_cast<void *>(info));
247 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
248 co->getInfo(info);
249 if (info->end_ip == 0)
250 return UNW_ENOINFO;
251 else
252 return UNW_ESUCCESS;
253}
254
255
256/// Resume execution at cursor position (aka longjump).
257_LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) {
Ed Masteadc29082016-08-30 15:38:10 +0000258 _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)", static_cast<void *>(cursor));
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000259 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
260 co->jumpto();
261 return UNW_EUNSPEC;
262}
263
264
265/// Get name of function at cursor position in stack frame.
266_LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf,
267 size_t bufLen, unw_word_t *offset) {
Ed Masteadc29082016-08-30 15:38:10 +0000268 _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000269 static_cast<void *>(cursor), static_cast<void *>(buf),
270 static_cast<unsigned long>(bufLen));
271 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
272 if (co->getFunctionName(buf, bufLen, offset))
273 return UNW_ESUCCESS;
274 else
275 return UNW_EUNSPEC;
276}
277
278
279/// Checks if a register is a floating-point register.
280_LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) {
Ed Masteadc29082016-08-30 15:38:10 +0000281 _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000282 static_cast<void *>(cursor), regNum);
283 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
284 return co->validFloatReg(regNum);
285}
286
287
288/// Checks if a register is a floating-point register.
289_LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor,
290 unw_regnum_t regNum) {
Ed Masteadc29082016-08-30 15:38:10 +0000291 _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000292 static_cast<void *>(cursor), regNum);
293 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
294 return co->getRegisterName(regNum);
295}
296
297
298/// Checks if current frame is signal trampoline.
299_LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) {
Ed Masteadc29082016-08-30 15:38:10 +0000300 _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000301 static_cast<void *>(cursor));
302 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
303 return co->isSignalFrame();
304}
305
306#ifdef __arm__
307// Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD
308_LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) {
Ed Masteadc29082016-08-30 15:38:10 +0000309 _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000310 static_cast<void *>(cursor));
311 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
312 return co->saveVFPAsX();
313}
314#endif
315
316
Ranjeet Singh7d674132017-03-31 15:28:06 +0000317#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Ed Maste63469ff2016-07-19 17:15:50 +0000318/// SPI: walks cached DWARF entries
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000319_LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)(
320 unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
Ed Masteadc29082016-08-30 15:38:10 +0000321 _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000322 reinterpret_cast<void *>(func));
323 DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
324}
325
326
327/// IPI: for __register_frame()
328void _unw_add_dynamic_fde(unw_word_t fde) {
329 CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
330 CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
331 const char *message = CFI_Parser<LocalAddressSpace>::decodeFDE(
332 LocalAddressSpace::sThisAddressSpace,
333 (LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo);
334 if (message == NULL) {
335 // dynamically registered FDEs don't have a mach_header group they are in.
336 // Use fde as mh_group
337 unw_word_t mh_group = fdeInfo.fdeStart;
338 DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group,
339 fdeInfo.pcStart, fdeInfo.pcEnd,
340 fdeInfo.fdeStart);
341 } else {
342 _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message);
343 }
344}
345
346/// IPI: for __deregister_frame()
347void _unw_remove_dynamic_fde(unw_word_t fde) {
348 // fde is own mh_group
349 DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
350}
Ranjeet Singh7d674132017-03-31 15:28:06 +0000351#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Martin Storsjoe53dc3f2017-09-26 08:07:26 +0000352#endif // !defined(__USING_SJLJ_EXCEPTIONS__)
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000353
354
355
356// Add logging hooks in Debug builds only
357#ifndef NDEBUG
358#include <stdlib.h>
359
360_LIBUNWIND_HIDDEN
361bool logAPIs() {
362 // do manual lock to avoid use of _cxa_guard_acquire or initializers
363 static bool checked = false;
364 static bool log = false;
365 if (!checked) {
366 log = (getenv("LIBUNWIND_PRINT_APIS") != NULL);
367 checked = true;
368 }
369 return log;
370}
371
372_LIBUNWIND_HIDDEN
373bool logUnwinding() {
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_UNWINDING") != NULL);
379 checked = true;
380 }
381 return log;
382}
383
Saleem Abdulrasoole1d4b2e2017-01-21 16:22:57 +0000384_LIBUNWIND_HIDDEN
385bool logDWARF() {
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_DWARF") != NULL);
391 checked = true;
392 }
393 return log;
394}
395
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000396#endif // NDEBUG
397