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