1288149Semaste//===--------------------------- libuwind.cpp -----------------------------===//
2288149Semaste//
3288149Semaste//                     The LLVM Compiler Infrastructure
4288149Semaste//
5288149Semaste// This file is dual licensed under the MIT and the University of Illinois Open
6288149Semaste// Source Licenses. See LICENSE.TXT for details.
7288149Semaste//
8288149Semaste//
9288149Semaste//  Implements unw_* functions from <libunwind.h>
10288149Semaste//
11288149Semaste//===----------------------------------------------------------------------===//
12288149Semaste
13288149Semaste#include <libunwind.h>
14288149Semaste
15288149Semaste#ifndef NDEBUG
16288149Semaste#include <cstdlib> // getenv
17288149Semaste#endif
18288149Semaste#include <new>
19288149Semaste#include <algorithm>
20288149Semaste
21288149Semaste#include "libunwind_ext.h"
22288149Semaste#include "config.h"
23288149Semaste
24288149Semaste#include <stdlib.h>
25288149Semaste
26288149Semaste
27288149Semaste#include "UnwindCursor.hpp"
28288149Semaste
29288149Semasteusing namespace libunwind;
30288149Semaste
31288149Semaste/// internal object to represent this processes address space
32288149SemasteLocalAddressSpace LocalAddressSpace::sThisAddressSpace;
33288149Semaste
34288149Semaste_LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space =
35288149Semaste    (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace;
36288149Semaste
37288149Semaste/// record the registers and stack position of the caller
38288149Semasteextern int unw_getcontext(unw_context_t *);
39288149Semaste// note: unw_getcontext() implemented in assembly
40288149Semaste
41288149Semaste/// Create a cursor of a thread in this process given 'context' recorded by
42288149Semaste/// unw_getcontext().
43288149Semaste_LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
44288149Semaste                                     unw_context_t *context) {
45288149Semaste  _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)\n",
46288149Semaste                       static_cast<void *>(cursor),
47288149Semaste                       static_cast<void *>(context));
48288149Semaste#if defined(__i386__)
49303196Semaste# define REGISTER_KIND Registers_x86
50288149Semaste#elif defined(__x86_64__)
51303196Semaste# define REGISTER_KIND Registers_x86_64
52288149Semaste#elif defined(__ppc__)
53303196Semaste# define REGISTER_KIND Registers_ppc
54303196Semaste#elif defined(__aarch64__)
55303196Semaste# define REGISTER_KIND Registers_arm64
56288149Semaste#elif _LIBUNWIND_ARM_EHABI
57303196Semaste# define REGISTER_KIND Registers_arm
58288149Semaste#elif defined(__or1k__)
59303196Semaste# define REGISTER_KIND Registers_or1k
60303196Semaste#elif defined(__riscv__)
61303196Semaste# define REGISTER_KIND Registers_riscv
62293183Semaste#elif defined(__mips__)
63303196Semaste# warning The MIPS architecture is not supported.
64288149Semaste#else
65303196Semaste# error Architecture not supported
66288149Semaste#endif
67303196Semaste  // Use "placement new" to allocate UnwindCursor in the cursor buffer.
68303196Semaste  new ((void *)cursor) UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
69303196Semaste                                 context, LocalAddressSpace::sThisAddressSpace);
70303196Semaste#undef REGISTER_KIND
71288149Semaste  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
72288149Semaste  co->setInfoBasedOnIPRegister();
73288149Semaste
74288149Semaste  return UNW_ESUCCESS;
75288149Semaste}
76288149Semaste
77288149Semaste#ifdef UNW_REMOTE
78288149Semaste/// Create a cursor into a thread in another process.
79288149Semaste_LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor,
80288149Semaste                                             unw_addr_space_t as,
81288149Semaste                                             void *arg) {
82288149Semaste  // special case: unw_init_remote(xx, unw_local_addr_space, xx)
83288149Semaste  if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace)
84288149Semaste    return unw_init_local(cursor, NULL); //FIXME
85288149Semaste
86288149Semaste  // use "placement new" to allocate UnwindCursor in the cursor buffer
87288149Semaste  switch (as->cpuType) {
88288149Semaste  case CPU_TYPE_I386:
89288149Semaste    new ((void *)cursor)
90288149Semaste        UnwindCursor<OtherAddressSpace<Pointer32<LittleEndian> >,
91288149Semaste                     Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg);
92288149Semaste    break;
93288149Semaste  case CPU_TYPE_X86_64:
94288149Semaste    new ((void *)cursor) UnwindCursor<
95288149Semaste        OtherAddressSpace<Pointer64<LittleEndian> >, Registers_x86_64>(
96288149Semaste        ((unw_addr_space_x86_64 *)as)->oas, arg);
97288149Semaste    break;
98288149Semaste  case CPU_TYPE_POWERPC:
99288149Semaste    new ((void *)cursor)
100288149Semaste        UnwindCursor<OtherAddressSpace<Pointer32<BigEndian> >, Registers_ppc>(
101288149Semaste            ((unw_addr_space_ppc *)as)->oas, arg);
102288149Semaste    break;
103288149Semaste  default:
104288149Semaste    return UNW_EUNSPEC;
105288149Semaste  }
106288149Semaste  return UNW_ESUCCESS;
107288149Semaste}
108288149Semaste
109288149Semaste
110288149Semastestatic bool is64bit(task_t task) {
111288149Semaste  return false; // FIXME
112288149Semaste}
113288149Semaste
114288149Semaste/// Create an address_space object for use in examining another task.
115288149Semaste_LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) {
116288149Semaste#if __i386__
117288149Semaste  if (is64bit(task)) {
118288149Semaste    unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task);
119288149Semaste    as->taskPort = task;
120288149Semaste    as->cpuType = CPU_TYPE_X86_64;
121288149Semaste    //as->oas
122288149Semaste  } else {
123288149Semaste    unw_addr_space_i386 *as = new unw_addr_space_i386(task);
124288149Semaste    as->taskPort = task;
125288149Semaste    as->cpuType = CPU_TYPE_I386;
126288149Semaste    //as->oas
127288149Semaste  }
128288149Semaste#else
129288149Semaste// FIXME
130288149Semaste#endif
131288149Semaste}
132288149Semaste
133288149Semaste
134288149Semaste/// Delete an address_space object.
135288149Semaste_LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) {
136288149Semaste  switch (asp->cpuType) {
137288149Semaste#if __i386__ || __x86_64__
138288149Semaste  case CPU_TYPE_I386: {
139288149Semaste    unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp;
140288149Semaste    delete as;
141288149Semaste  }
142288149Semaste  break;
143288149Semaste  case CPU_TYPE_X86_64: {
144288149Semaste    unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp;
145288149Semaste    delete as;
146288149Semaste  }
147288149Semaste  break;
148288149Semaste#endif
149288149Semaste  case CPU_TYPE_POWERPC: {
150288149Semaste    unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp;
151288149Semaste    delete as;
152288149Semaste  }
153288149Semaste  break;
154288149Semaste  }
155288149Semaste}
156288149Semaste#endif // UNW_REMOTE
157288149Semaste
158288149Semaste
159288149Semaste/// Get value of specified register at cursor position in stack frame.
160288149Semaste_LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
161288149Semaste                                  unw_word_t *value) {
162288149Semaste  _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)\n",
163288149Semaste                       static_cast<void *>(cursor), regNum,
164288149Semaste                       static_cast<void *>(value));
165288149Semaste  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
166288149Semaste  if (co->validReg(regNum)) {
167288149Semaste    *value = co->getReg(regNum);
168288149Semaste    return UNW_ESUCCESS;
169288149Semaste  }
170288149Semaste  return UNW_EBADREG;
171288149Semaste}
172288149Semaste
173288149Semaste
174288149Semaste/// Set value of specified register at cursor position in stack frame.
175288149Semaste_LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
176288149Semaste                                  unw_word_t value) {
177288149Semaste  _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)\n",
178288149Semaste                       static_cast<void *>(cursor), regNum, (long long)value);
179288149Semaste  typedef LocalAddressSpace::pint_t pint_t;
180288149Semaste  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
181288149Semaste  if (co->validReg(regNum)) {
182288149Semaste    co->setReg(regNum, (pint_t)value);
183288149Semaste    // specical case altering IP to re-find info (being called by personality
184288149Semaste    // function)
185288149Semaste    if (regNum == UNW_REG_IP)
186288149Semaste      co->setInfoBasedOnIPRegister(false);
187288149Semaste    return UNW_ESUCCESS;
188288149Semaste  }
189288149Semaste  return UNW_EBADREG;
190288149Semaste}
191288149Semaste
192288149Semaste
193288149Semaste/// Get value of specified float register at cursor position in stack frame.
194288149Semaste_LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
195288149Semaste                                    unw_fpreg_t *value) {
196288149Semaste  _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)\n",
197288149Semaste                       static_cast<void *>(cursor), regNum,
198288149Semaste                       static_cast<void *>(value));
199288149Semaste  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
200288149Semaste  if (co->validFloatReg(regNum)) {
201288149Semaste    *value = co->getFloatReg(regNum);
202288149Semaste    return UNW_ESUCCESS;
203288149Semaste  }
204288149Semaste  return UNW_EBADREG;
205288149Semaste}
206288149Semaste
207288149Semaste
208288149Semaste/// Set value of specified float register at cursor position in stack frame.
209288149Semaste_LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
210288149Semaste                                    unw_fpreg_t value) {
211288149Semaste#if _LIBUNWIND_ARM_EHABI
212288149Semaste  _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)\n",
213288149Semaste                       static_cast<void *>(cursor), regNum, value);
214288149Semaste#else
215288149Semaste  _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)\n",
216288149Semaste                       static_cast<void *>(cursor), regNum, value);
217288149Semaste#endif
218288149Semaste  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
219288149Semaste  if (co->validFloatReg(regNum)) {
220288149Semaste    co->setFloatReg(regNum, value);
221288149Semaste    return UNW_ESUCCESS;
222288149Semaste  }
223288149Semaste  return UNW_EBADREG;
224288149Semaste}
225288149Semaste
226288149Semaste
227288149Semaste/// Move cursor to next frame.
228288149Semaste_LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) {
229288149Semaste  _LIBUNWIND_TRACE_API("unw_step(cursor=%p)\n", static_cast<void *>(cursor));
230288149Semaste  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
231288149Semaste  return co->step();
232288149Semaste}
233288149Semaste
234288149Semaste
235288149Semaste/// Get unwind info at cursor position in stack frame.
236288149Semaste_LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor,
237288149Semaste                                        unw_proc_info_t *info) {
238288149Semaste  _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)\n",
239288149Semaste                       static_cast<void *>(cursor), static_cast<void *>(info));
240288149Semaste  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
241288149Semaste  co->getInfo(info);
242288149Semaste  if (info->end_ip == 0)
243288149Semaste    return UNW_ENOINFO;
244288149Semaste  else
245288149Semaste    return UNW_ESUCCESS;
246288149Semaste}
247288149Semaste
248288149Semaste
249288149Semaste/// Resume execution at cursor position (aka longjump).
250288149Semaste_LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) {
251288149Semaste  _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)\n", static_cast<void *>(cursor));
252288149Semaste  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
253288149Semaste  co->jumpto();
254288149Semaste  return UNW_EUNSPEC;
255288149Semaste}
256288149Semaste
257288149Semaste
258288149Semaste/// Get name of function at cursor position in stack frame.
259288149Semaste_LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf,
260288149Semaste                                        size_t bufLen, unw_word_t *offset) {
261288149Semaste  _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)\n",
262288149Semaste                       static_cast<void *>(cursor), static_cast<void *>(buf),
263288149Semaste                       static_cast<unsigned long>(bufLen));
264288149Semaste  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
265288149Semaste  if (co->getFunctionName(buf, bufLen, offset))
266288149Semaste    return UNW_ESUCCESS;
267288149Semaste  else
268288149Semaste    return UNW_EUNSPEC;
269288149Semaste}
270288149Semaste
271288149Semaste
272288149Semaste/// Checks if a register is a floating-point register.
273288149Semaste_LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) {
274288149Semaste  _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)\n",
275288149Semaste                       static_cast<void *>(cursor), regNum);
276288149Semaste  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
277288149Semaste  return co->validFloatReg(regNum);
278288149Semaste}
279288149Semaste
280288149Semaste
281288149Semaste/// Checks if a register is a floating-point register.
282288149Semaste_LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor,
283288149Semaste                                          unw_regnum_t regNum) {
284288149Semaste  _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)\n",
285288149Semaste                       static_cast<void *>(cursor), regNum);
286288149Semaste  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
287288149Semaste  return co->getRegisterName(regNum);
288288149Semaste}
289288149Semaste
290288149Semaste
291288149Semaste/// Checks if current frame is signal trampoline.
292288149Semaste_LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) {
293288149Semaste  _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)\n",
294288149Semaste                       static_cast<void *>(cursor));
295288149Semaste  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
296288149Semaste  return co->isSignalFrame();
297288149Semaste}
298288149Semaste
299288149Semaste#ifdef __arm__
300288149Semaste// Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD
301288149Semaste_LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) {
302288149Semaste  _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)\n",
303288149Semaste                       static_cast<void *>(cursor));
304288149Semaste  AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
305288149Semaste  return co->saveVFPAsX();
306288149Semaste}
307288149Semaste#endif
308288149Semaste
309288149Semaste
310288149Semaste#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
311288149Semaste/// SPI: walks cached dwarf entries
312288149Semaste_LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)(
313288149Semaste    unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
314288149Semaste  _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)\n",
315288149Semaste                       reinterpret_cast<void *>(func));
316288149Semaste  DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
317288149Semaste}
318288149Semaste
319288149Semaste
320288149Semaste/// IPI: for __register_frame()
321288149Semastevoid _unw_add_dynamic_fde(unw_word_t fde) {
322288149Semaste  CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
323288149Semaste  CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
324288149Semaste  const char *message = CFI_Parser<LocalAddressSpace>::decodeFDE(
325288149Semaste                           LocalAddressSpace::sThisAddressSpace,
326288149Semaste                          (LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo);
327288149Semaste  if (message == NULL) {
328288149Semaste    // dynamically registered FDEs don't have a mach_header group they are in.
329288149Semaste    // Use fde as mh_group
330288149Semaste    unw_word_t mh_group = fdeInfo.fdeStart;
331288149Semaste    DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group,
332288149Semaste                                          fdeInfo.pcStart, fdeInfo.pcEnd,
333288149Semaste                                          fdeInfo.fdeStart);
334288149Semaste  } else {
335288149Semaste    _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message);
336288149Semaste  }
337288149Semaste}
338288149Semaste
339288149Semaste/// IPI: for __deregister_frame()
340288149Semastevoid _unw_remove_dynamic_fde(unw_word_t fde) {
341288149Semaste  // fde is own mh_group
342288149Semaste  DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
343288149Semaste}
344288149Semaste#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
345288149Semaste
346288149Semaste
347288149Semaste
348288149Semaste// Add logging hooks in Debug builds only
349288149Semaste#ifndef NDEBUG
350288149Semaste#include <stdlib.h>
351288149Semaste
352288149Semaste_LIBUNWIND_HIDDEN
353288149Semastebool logAPIs() {
354288149Semaste  // do manual lock to avoid use of _cxa_guard_acquire or initializers
355288149Semaste  static bool checked = false;
356288149Semaste  static bool log = false;
357288149Semaste  if (!checked) {
358288149Semaste    log = (getenv("LIBUNWIND_PRINT_APIS") != NULL);
359288149Semaste    checked = true;
360288149Semaste  }
361288149Semaste  return log;
362288149Semaste}
363288149Semaste
364288149Semaste_LIBUNWIND_HIDDEN
365288149Semastebool logUnwinding() {
366288149Semaste  // do manual lock to avoid use of _cxa_guard_acquire or initializers
367288149Semaste  static bool checked = false;
368288149Semaste  static bool log = false;
369288149Semaste  if (!checked) {
370288149Semaste    log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL);
371288149Semaste    checked = true;
372288149Semaste  }
373288149Semaste  return log;
374288149Semaste}
375288149Semaste
376288149Semaste#endif // NDEBUG
377288149Semaste
378