blob: 60354492df7cbfed8ca5fe727c2838483449812c [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
27#include "UnwindCursor.hpp"
28
29using namespace libunwind;
30
31/// internal object to represent this processes address space
32LocalAddressSpace LocalAddressSpace::sThisAddressSpace;
33
34_LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space =
35 (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace;
36
37/// record the registers and stack position of the caller
38extern int unw_getcontext(unw_context_t *);
39// note: unw_getcontext() implemented in assembly
40
41/// Create a cursor of a thread in this process given 'context' recorded by
42/// unw_getcontext().
43_LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
44 unw_context_t *context) {
Ed Masteadc29082016-08-30 15:38:10 +000045 _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +000046 static_cast<void *>(cursor),
47 static_cast<void *>(context));
Saleem Abdulrasool675df582015-04-24 19:39:17 +000048#if defined(__i386__)
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000049# define REGISTER_KIND Registers_x86
Saleem Abdulrasool675df582015-04-24 19:39:17 +000050#elif defined(__x86_64__)
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000051# define REGISTER_KIND Registers_x86_64
Saleem Abdulrasool675df582015-04-24 19:39:17 +000052#elif defined(__ppc__)
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000053# define REGISTER_KIND Registers_ppc
54#elif defined(__aarch64__)
55# define REGISTER_KIND Registers_arm64
Logan Chien61278582015-07-19 15:23:10 +000056#elif _LIBUNWIND_ARM_EHABI
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000057# define REGISTER_KIND Registers_arm
Peter Zotovd4255ab2015-08-31 05:26:37 +000058#elif defined(__or1k__)
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000059# define REGISTER_KIND Registers_or1k
Vasileios Kalintirisdb1c2632015-09-26 18:26:01 +000060#elif defined(__mips__)
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000061# warning The MIPS architecture is not supported.
Ed Maste40377de2015-08-13 14:21:03 +000062#else
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000063# error Architecture not supported
Saleem Abdulrasool675df582015-04-24 19:39:17 +000064#endif
Asiri Rathnayaked2d1ea92016-05-25 12:36:34 +000065 // Use "placement new" to allocate UnwindCursor in the cursor buffer.
66 new ((void *)cursor) UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
67 context, LocalAddressSpace::sThisAddressSpace);
68#undef REGISTER_KIND
Saleem Abdulrasool675df582015-04-24 19:39:17 +000069 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
70 co->setInfoBasedOnIPRegister();
71
72 return UNW_ESUCCESS;
73}
74
75#ifdef UNW_REMOTE
76/// Create a cursor into a thread in another process.
77_LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor,
78 unw_addr_space_t as,
79 void *arg) {
80 // special case: unw_init_remote(xx, unw_local_addr_space, xx)
81 if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace)
82 return unw_init_local(cursor, NULL); //FIXME
83
84 // use "placement new" to allocate UnwindCursor in the cursor buffer
85 switch (as->cpuType) {
86 case CPU_TYPE_I386:
87 new ((void *)cursor)
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +000088 UnwindCursor<RemoteAddressSpace<Pointer32<LittleEndian>>,
Saleem Abdulrasool675df582015-04-24 19:39:17 +000089 Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg);
90 break;
91 case CPU_TYPE_X86_64:
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +000092 new ((void *)cursor)
93 UnwindCursor<RemoteAddressSpace<Pointer64<LittleEndian>>,
94 Registers_x86_64>(((unw_addr_space_x86_64 *)as)->oas, arg);
Saleem Abdulrasool675df582015-04-24 19:39:17 +000095 break;
96 case CPU_TYPE_POWERPC:
97 new ((void *)cursor)
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +000098 UnwindCursor<RemoteAddressSpace<Pointer32<BigEndian>>,
99 Registers_ppc>(((unw_addr_space_ppc *)as)->oas, arg);
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000100 break;
101 default:
102 return UNW_EUNSPEC;
103 }
104 return UNW_ESUCCESS;
105}
106
107
108static bool is64bit(task_t task) {
109 return false; // FIXME
110}
111
112/// Create an address_space object for use in examining another task.
113_LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) {
114#if __i386__
115 if (is64bit(task)) {
116 unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task);
117 as->taskPort = task;
118 as->cpuType = CPU_TYPE_X86_64;
119 //as->oas
120 } else {
121 unw_addr_space_i386 *as = new unw_addr_space_i386(task);
122 as->taskPort = task;
123 as->cpuType = CPU_TYPE_I386;
124 //as->oas
125 }
126#else
127// FIXME
128#endif
129}
130
131
132/// Delete an address_space object.
133_LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) {
134 switch (asp->cpuType) {
135#if __i386__ || __x86_64__
136 case CPU_TYPE_I386: {
137 unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp;
138 delete as;
139 }
140 break;
141 case CPU_TYPE_X86_64: {
142 unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp;
143 delete as;
144 }
145 break;
146#endif
147 case CPU_TYPE_POWERPC: {
148 unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp;
149 delete as;
150 }
151 break;
152 }
153}
154#endif // UNW_REMOTE
155
156
157/// Get value of specified register at cursor position in stack frame.
158_LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
159 unw_word_t *value) {
Ed Masteadc29082016-08-30 15:38:10 +0000160 _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000161 static_cast<void *>(cursor), regNum,
162 static_cast<void *>(value));
163 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
164 if (co->validReg(regNum)) {
165 *value = co->getReg(regNum);
166 return UNW_ESUCCESS;
167 }
168 return UNW_EBADREG;
169}
170
171
172/// Set value of specified register at cursor position in stack frame.
173_LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
174 unw_word_t value) {
Ed Masteadc29082016-08-30 15:38:10 +0000175 _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000176 static_cast<void *>(cursor), regNum, (long long)value);
177 typedef LocalAddressSpace::pint_t pint_t;
178 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
179 if (co->validReg(regNum)) {
180 co->setReg(regNum, (pint_t)value);
181 // specical case altering IP to re-find info (being called by personality
182 // function)
183 if (regNum == UNW_REG_IP)
184 co->setInfoBasedOnIPRegister(false);
185 return UNW_ESUCCESS;
186 }
187 return UNW_EBADREG;
188}
189
190
191/// Get value of specified float register at cursor position in stack frame.
192_LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
193 unw_fpreg_t *value) {
Ed Masteadc29082016-08-30 15:38:10 +0000194 _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000195 static_cast<void *>(cursor), regNum,
196 static_cast<void *>(value));
197 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
198 if (co->validFloatReg(regNum)) {
199 *value = co->getFloatReg(regNum);
200 return UNW_ESUCCESS;
201 }
202 return UNW_EBADREG;
203}
204
205
206/// Set value of specified float register at cursor position in stack frame.
207_LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
208 unw_fpreg_t value) {
Logan Chien61278582015-07-19 15:23:10 +0000209#if _LIBUNWIND_ARM_EHABI
Ed Masteadc29082016-08-30 15:38:10 +0000210 _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000211 static_cast<void *>(cursor), regNum, value);
212#else
Ed Masteadc29082016-08-30 15:38:10 +0000213 _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000214 static_cast<void *>(cursor), regNum, value);
215#endif
216 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
217 if (co->validFloatReg(regNum)) {
218 co->setFloatReg(regNum, value);
219 return UNW_ESUCCESS;
220 }
221 return UNW_EBADREG;
222}
223
224
225/// Move cursor to next frame.
226_LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) {
Ed Masteadc29082016-08-30 15:38:10 +0000227 _LIBUNWIND_TRACE_API("unw_step(cursor=%p)", static_cast<void *>(cursor));
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000228 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
229 return co->step();
230}
231
232
233/// Get unwind info at cursor position in stack frame.
234_LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor,
235 unw_proc_info_t *info) {
Ed Masteadc29082016-08-30 15:38:10 +0000236 _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000237 static_cast<void *>(cursor), static_cast<void *>(info));
238 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
239 co->getInfo(info);
240 if (info->end_ip == 0)
241 return UNW_ENOINFO;
242 else
243 return UNW_ESUCCESS;
244}
245
246
247/// Resume execution at cursor position (aka longjump).
248_LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) {
Ed Masteadc29082016-08-30 15:38:10 +0000249 _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)", static_cast<void *>(cursor));
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000250 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
251 co->jumpto();
252 return UNW_EUNSPEC;
253}
254
255
256/// Get name of function at cursor position in stack frame.
257_LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf,
258 size_t bufLen, unw_word_t *offset) {
Ed Masteadc29082016-08-30 15:38:10 +0000259 _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000260 static_cast<void *>(cursor), static_cast<void *>(buf),
261 static_cast<unsigned long>(bufLen));
262 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
263 if (co->getFunctionName(buf, bufLen, offset))
264 return UNW_ESUCCESS;
265 else
266 return UNW_EUNSPEC;
267}
268
269
270/// Checks if a register is a floating-point register.
271_LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) {
Ed Masteadc29082016-08-30 15:38:10 +0000272 _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000273 static_cast<void *>(cursor), regNum);
274 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
275 return co->validFloatReg(regNum);
276}
277
278
279/// Checks if a register is a floating-point register.
280_LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor,
281 unw_regnum_t regNum) {
Ed Masteadc29082016-08-30 15:38:10 +0000282 _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000283 static_cast<void *>(cursor), regNum);
284 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
285 return co->getRegisterName(regNum);
286}
287
288
289/// Checks if current frame is signal trampoline.
290_LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) {
Ed Masteadc29082016-08-30 15:38:10 +0000291 _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000292 static_cast<void *>(cursor));
293 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
294 return co->isSignalFrame();
295}
296
297#ifdef __arm__
298// Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD
299_LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) {
Ed Masteadc29082016-08-30 15:38:10 +0000300 _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000301 static_cast<void *>(cursor));
302 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
303 return co->saveVFPAsX();
304}
305#endif
306
307
308#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
Ed Maste63469ff2016-07-19 17:15:50 +0000309/// SPI: walks cached DWARF entries
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000310_LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)(
311 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 +0000312 _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000313 reinterpret_cast<void *>(func));
314 DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
315}
316
317
318/// IPI: for __register_frame()
319void _unw_add_dynamic_fde(unw_word_t fde) {
320 CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
321 CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
322 const char *message = CFI_Parser<LocalAddressSpace>::decodeFDE(
323 LocalAddressSpace::sThisAddressSpace,
324 (LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo);
325 if (message == NULL) {
326 // dynamically registered FDEs don't have a mach_header group they are in.
327 // Use fde as mh_group
328 unw_word_t mh_group = fdeInfo.fdeStart;
329 DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group,
330 fdeInfo.pcStart, fdeInfo.pcEnd,
331 fdeInfo.fdeStart);
332 } else {
333 _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message);
334 }
335}
336
337/// IPI: for __deregister_frame()
338void _unw_remove_dynamic_fde(unw_word_t fde) {
339 // fde is own mh_group
340 DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
341}
342#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
343
344
345
346// Add logging hooks in Debug builds only
347#ifndef NDEBUG
348#include <stdlib.h>
349
350_LIBUNWIND_HIDDEN
351bool logAPIs() {
352 // do manual lock to avoid use of _cxa_guard_acquire or initializers
353 static bool checked = false;
354 static bool log = false;
355 if (!checked) {
356 log = (getenv("LIBUNWIND_PRINT_APIS") != NULL);
357 checked = true;
358 }
359 return log;
360}
361
362_LIBUNWIND_HIDDEN
363bool logUnwinding() {
364 // do manual lock to avoid use of _cxa_guard_acquire or initializers
365 static bool checked = false;
366 static bool log = false;
367 if (!checked) {
368 log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL);
369 checked = true;
370 }
371 return log;
372}
373
374#endif // NDEBUG
375