~ubuntu-branches/ubuntu/trusty/emscripten/trusty-proposed

« back to all changes in this revision

Viewing changes to system/lib/libcxxabi/src/Unwind/libunwind.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2014-01-19 14:12:40 UTC
  • mfrom: (1.2.4)
  • Revision ID: package-import@ubuntu.com-20140119141240-jg1l42cc158j59tn
Tags: 1.9.0~20140119~7dc8c2f-1
* New snapshot release (Closes: #733714)
* Provide sources for javascript and flash. Done in orig-tar.sh
  Available in third_party/websockify/include/web-socket-js/src/
  (Closes: #735903)

Show diffs side-by-side

added added

removed removed

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