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