1 //===--------------------------- libuwind.cpp -----------------------------===//
2 //
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>
19 #include <tuple>
20 #include <memory>
21 #include <vector>
22 #include <algorithm>
23 
24 #include "libunwind_ext.h"
25 #include "config.h"
26 
27 #include <stdlib.h>
28 
29 
30 #include "UnwindCursor.hpp"
31 
32 using namespace libunwind;
33 
34 /// internal object to represent this processes address space
35 LocalAddressSpace LocalAddressSpace::sThisAddressSpace;
36 
37 _LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space =
38     (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace;
39 
40 /// record the registers and stack position of the caller
41 extern int unw_getcontext(unw_context_t *);
42 // note: unw_getcontext() implemented in assembly
43 
44 /// Create a cursor of a thread in this process given 'context' recorded by
45 /// unw_getcontext().
46 _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
47                                      unw_context_t *context) {
48   _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)\n",
49                        static_cast<void *>(cursor),
50                        static_cast<void *>(context));
51   // Use "placement new" to allocate UnwindCursor in the cursor buffer.
52 #if defined(__i386__)
53   new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86>(
54                                  context, LocalAddressSpace::sThisAddressSpace);
55 #elif defined(__x86_64__)
56   new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86_64>(
57                                  context, LocalAddressSpace::sThisAddressSpace);
58 #elif defined(__ppc__)
59   new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_ppc>(
60                                  context, LocalAddressSpace::sThisAddressSpace);
61 #elif defined(__arm64__)
62   new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm64>(
63                                  context, LocalAddressSpace::sThisAddressSpace);
64 #elif LIBCXXABI_ARM_EHABI
65   new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm>(
66                                  context, LocalAddressSpace::sThisAddressSpace);
67 #endif
68   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
69   co->setInfoBasedOnIPRegister();
70 
71   return UNW_ESUCCESS;
72 }
73 
74 #ifdef UNW_REMOTE
75 /// Create a cursor into a thread in another process.
76 _LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor,
77                                              unw_addr_space_t as,
78                                              void *arg) {
79   // special case: unw_init_remote(xx, unw_local_addr_space, xx)
80   if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace)
81     return unw_init_local(cursor, NULL); //FIXME
82 
83   // use "placement new" to allocate UnwindCursor in the cursor buffer
84   switch (as->cpuType) {
85   case CPU_TYPE_I386:
86     new ((void *)cursor)
87         UnwindCursor<OtherAddressSpace<Pointer32<LittleEndian> >,
88                      Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg);
89     break;
90   case CPU_TYPE_X86_64:
91     new ((void *)cursor) UnwindCursor<
92         OtherAddressSpace<Pointer64<LittleEndian> >, Registers_x86_64>(
93         ((unw_addr_space_x86_64 *)as)->oas, arg);
94     break;
95   case CPU_TYPE_POWERPC:
96     new ((void *)cursor)
97         UnwindCursor<OtherAddressSpace<Pointer32<BigEndian> >, Registers_ppc>(
98             ((unw_addr_space_ppc *)as)->oas, arg);
99     break;
100   default:
101     return UNW_EUNSPEC;
102   }
103   return UNW_ESUCCESS;
104 }
105 
106 
107 static bool is64bit(task_t task) {
108   return false; // FIXME
109 }
110 
111 /// Create an address_space object for use in examining another task.
112 _LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) {
113 #if __i386__
114   if (is64bit(task)) {
115     unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task);
116     as->taskPort = task;
117     as->cpuType = CPU_TYPE_X86_64;
118     //as->oas
119   } else {
120     unw_addr_space_i386 *as = new unw_addr_space_i386(task);
121     as->taskPort = task;
122     as->cpuType = CPU_TYPE_I386;
123     //as->oas
124   }
125 #else
126 // FIXME
127 #endif
128 }
129 
130 
131 /// Delete an address_space object.
132 _LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) {
133   switch (asp->cpuType) {
134 #if __i386__ || __x86_64__
135   case CPU_TYPE_I386: {
136     unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp;
137     delete as;
138   }
139   break;
140   case CPU_TYPE_X86_64: {
141     unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp;
142     delete as;
143   }
144   break;
145 #endif
146   case CPU_TYPE_POWERPC: {
147     unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp;
148     delete as;
149   }
150   break;
151   }
152 }
153 #endif // UNW_REMOTE
154 
155 
156 /// Get value of specified register at cursor position in stack frame.
157 _LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
158                                   unw_word_t *value) {
159   _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)\n",
160                        static_cast<void *>(cursor), regNum,
161                        static_cast<void *>(value));
162   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
163   if (co->validReg(regNum)) {
164     *value = co->getReg(regNum);
165     return UNW_ESUCCESS;
166   }
167   return UNW_EBADREG;
168 }
169 
170 
171 /// Set value of specified register at cursor position in stack frame.
172 _LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
173                                   unw_word_t value) {
174   _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)\n",
175                        static_cast<void *>(cursor), regNum, (long long)value);
176   typedef LocalAddressSpace::pint_t pint_t;
177   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
178   if (co->validReg(regNum)) {
179     co->setReg(regNum, (pint_t)value);
180     // specical case altering IP to re-find info (being called by personality
181     // function)
182     if (regNum == UNW_REG_IP)
183       co->setInfoBasedOnIPRegister(false);
184     return UNW_ESUCCESS;
185   }
186   return UNW_EBADREG;
187 }
188 
189 
190 /// Get value of specified float register at cursor position in stack frame.
191 _LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
192                                     unw_fpreg_t *value) {
193   _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)\n",
194                        static_cast<void *>(cursor), regNum,
195                        static_cast<void *>(value));
196   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
197   if (co->validFloatReg(regNum)) {
198     *value = co->getFloatReg(regNum);
199     return UNW_ESUCCESS;
200   }
201   return UNW_EBADREG;
202 }
203 
204 
205 /// Set value of specified float register at cursor position in stack frame.
206 _LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
207                                     unw_fpreg_t value) {
208 #if LIBCXXABI_ARM_EHABI
209   _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)\n",
210                        static_cast<void *>(cursor), regNum, value);
211 #else
212   _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)\n",
213                        static_cast<void *>(cursor), regNum, value);
214 #endif
215   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
216   if (co->validFloatReg(regNum)) {
217     co->setFloatReg(regNum, value);
218     return UNW_ESUCCESS;
219   }
220   return UNW_EBADREG;
221 }
222 
223 
224 /// Move cursor to next frame.
225 _LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) {
226   _LIBUNWIND_TRACE_API("unw_step(cursor=%p)\n", static_cast<void *>(cursor));
227   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
228   return co->step();
229 }
230 
231 
232 /// Get unwind info at cursor position in stack frame.
233 _LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor,
234                                         unw_proc_info_t *info) {
235   _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)\n",
236                        static_cast<void *>(cursor), static_cast<void *>(info));
237   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
238   co->getInfo(info);
239   if (info->end_ip == 0)
240     return UNW_ENOINFO;
241   else
242     return UNW_ESUCCESS;
243 }
244 
245 
246 /// Resume execution at cursor position (aka longjump).
247 _LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) {
248   _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)\n", static_cast<void *>(cursor));
249   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
250   co->jumpto();
251   return UNW_EUNSPEC;
252 }
253 
254 
255 /// Get name of function at cursor position in stack frame.
256 _LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf,
257                                         size_t bufLen, unw_word_t *offset) {
258   _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)\n",
259                        static_cast<void *>(cursor), static_cast<void *>(buf),
260                        static_cast<unsigned long>(bufLen));
261   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
262   if (co->getFunctionName(buf, bufLen, offset))
263     return UNW_ESUCCESS;
264   else
265     return UNW_EUNSPEC;
266 }
267 
268 
269 /// Checks if a register is a floating-point register.
270 _LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) {
271   _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)\n",
272                        static_cast<void *>(cursor), regNum);
273   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
274   return co->validFloatReg(regNum);
275 }
276 
277 
278 /// Checks if a register is a floating-point register.
279 _LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor,
280                                           unw_regnum_t regNum) {
281   _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)\n",
282                        static_cast<void *>(cursor), regNum);
283   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
284   return co->getRegisterName(regNum);
285 }
286 
287 
288 /// Checks if current frame is signal trampoline.
289 _LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) {
290   _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)\n",
291                        static_cast<void *>(cursor));
292   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
293   return co->isSignalFrame();
294 }
295 
296 #ifdef __arm__
297 // Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD
298 _LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) {
299   _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)\n",
300                        static_cast<void *>(cursor));
301   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
302   return co->saveVFPAsX();
303 }
304 #endif
305 
306 
307 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
308 /// SPI: walks cached dwarf entries
309 _LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)(
310     unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
311   _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)\n",
312                        reinterpret_cast<void *>(func));
313   DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
314 }
315 
316 
317 /// IPI: for __register_frame()
318 void _unw_add_dynamic_fde(unw_word_t fde) {
319   CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
320   CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
321   const char *message = CFI_Parser<LocalAddressSpace>::decodeFDE(
322                            LocalAddressSpace::sThisAddressSpace,
323                           (LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo);
324   if (message == NULL) {
325     // dynamically registered FDEs don't have a mach_header group they are in.
326     // Use fde as mh_group
327     unw_word_t mh_group = fdeInfo.fdeStart;
328     DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group,
329                                           fdeInfo.pcStart, fdeInfo.pcEnd,
330                                           fdeInfo.fdeStart);
331   } else {
332     _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message);
333   }
334 }
335 
336 /// IPI: for __deregister_frame()
337 void _unw_remove_dynamic_fde(unw_word_t fde) {
338   // fde is own mh_group
339   DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
340 }
341 #endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
342 
343 
344 
345 // Add logging hooks in Debug builds only
346 #ifndef NDEBUG
347 #include <stdlib.h>
348 
349 _LIBUNWIND_HIDDEN
350 bool logAPIs() {
351   // do manual lock to avoid use of _cxa_guard_acquire or initializers
352   static bool checked = false;
353   static bool log = false;
354   if (!checked) {
355     log = (getenv("LIBUNWIND_PRINT_APIS") != NULL);
356     checked = true;
357   }
358   return log;
359 }
360 
361 _LIBUNWIND_HIDDEN
362 bool logUnwinding() {
363   // do manual lock to avoid use of _cxa_guard_acquire or initializers
364   static bool checked = false;
365   static bool log = false;
366   if (!checked) {
367     log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL);
368     checked = true;
369   }
370   return log;
371 }
372 
373 #endif // NDEBUG
374 
375