~ubuntu-branches/ubuntu/vivid/emscripten/vivid-proposed

« back to all changes in this revision

Viewing changes to system/lib/libcxxabi/src/Unwind/AddressSpace.hpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2014-01-19 14:12:40 UTC
  • mfrom: (4.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20140119141240-nfiw0p8033oitpfz
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
//===------------------------- AddressSpace.hpp ---------------------------===//
 
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
// Abstracts accessing local vs remote address spaces.
 
10
//
 
11
//===----------------------------------------------------------------------===//
 
12
 
 
13
#ifndef __ADDRESSSPACE_HPP__
 
14
#define __ADDRESSSPACE_HPP__
 
15
 
 
16
#include <stdint.h>
 
17
#include <stdio.h>
 
18
#include <stdlib.h>
 
19
#include <dlfcn.h>
 
20
 
 
21
#if __APPLE__
 
22
#include <mach-o/getsect.h>
 
23
namespace libunwind {
 
24
   bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde);
 
25
}
 
26
#endif
 
27
 
 
28
#include "libunwind.h"
 
29
#include "config.h"
 
30
#include "dwarf2.h"
 
31
#include "Registers.hpp"
 
32
 
 
33
namespace libunwind {
 
34
 
 
35
/// Used by findUnwindSections() to return info about needed sections.
 
36
struct UnwindInfoSections {
 
37
  uintptr_t        dso_base;
 
38
#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
 
39
  uintptr_t       dwarf_section;
 
40
  uintptr_t       dwarf_section_length;
 
41
#endif
 
42
#if _LIBUNWIND_SUPPORT_DWARF_INDEX
 
43
  uintptr_t       dwarf_index_section;
 
44
  uintptr_t       dwarf_index_section_length;
 
45
#endif
 
46
#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
 
47
  uintptr_t       compact_unwind_section;
 
48
  uintptr_t       compact_unwind_section_length;
 
49
#endif
 
50
};
 
51
 
 
52
 
 
53
/// LocalAddressSpace is used as a template parameter to UnwindCursor when
 
54
/// unwinding a thread in the same process.  The wrappers compile away,
 
55
/// making local unwinds fast.
 
56
class __attribute__((visibility("hidden"))) LocalAddressSpace {
 
57
public:
 
58
#if __LP64__
 
59
  typedef uint64_t pint_t;
 
60
  typedef int64_t  sint_t;
 
61
#else
 
62
  typedef uint32_t pint_t;
 
63
  typedef int32_t  sint_t;
 
64
#endif
 
65
  uint8_t         get8(pint_t addr)      { return *((uint8_t *)addr); }
 
66
  uint16_t        get16(pint_t addr)     { return *((uint16_t *)addr); }
 
67
  uint32_t        get32(pint_t addr)     { return *((uint32_t *)addr); }
 
68
  uint64_t        get64(pint_t addr)     { return *((uint64_t *)addr); }
 
69
  double          getDouble(pint_t addr) { return *((double *)addr); }
 
70
  v128            getVector(pint_t addr) { return *((v128 *)addr); }
 
71
  uintptr_t       getP(pint_t addr);
 
72
  static uint64_t getULEB128(pint_t &addr, pint_t end);
 
73
  static int64_t  getSLEB128(pint_t &addr, pint_t end);
 
74
 
 
75
  pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding);
 
76
  bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
 
77
                        unw_word_t *offset);
 
78
  bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
 
79
  bool findOtherFDE(pint_t targetAddr, pint_t &fde);
 
80
 
 
81
  static LocalAddressSpace sThisAddressSpace;
 
82
};
 
83
 
 
84
 
 
85
inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
 
86
#if __LP64__
 
87
  return get64(addr);
 
88
#else
 
89
  return get32(addr);
 
90
#endif
 
91
}
 
92
 
 
93
/// Read a ULEB128 into a 64-bit word.
 
94
inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
 
95
  const uint8_t *p = (uint8_t *)addr;
 
96
  const uint8_t *pend = (uint8_t *)end;
 
97
  uint64_t result = 0;
 
98
  int bit = 0;
 
99
  do {
 
100
    uint64_t b;
 
101
 
 
102
    if (p == pend)
 
103
      _LIBUNWIND_ABORT("truncated uleb128 expression");
 
104
 
 
105
    b = *p & 0x7f;
 
106
 
 
107
    if (bit >= 64 || b << bit >> bit != b) {
 
108
      _LIBUNWIND_ABORT("malformed uleb128 expression");
 
109
    } else {
 
110
      result |= b << bit;
 
111
      bit += 7;
 
112
    }
 
113
  } while (*p++ >= 0x80);
 
114
  addr = (pint_t) p;
 
115
  return result;
 
116
}
 
117
 
 
118
/// Read a SLEB128 into a 64-bit word.
 
119
inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
 
120
  const uint8_t *p = (uint8_t *)addr;
 
121
  const uint8_t *pend = (uint8_t *)end;
 
122
  int64_t result = 0;
 
123
  int bit = 0;
 
124
  uint8_t byte;
 
125
  do {
 
126
    if (p == pend)
 
127
      _LIBUNWIND_ABORT("truncated sleb128 expression");
 
128
    byte = *p++;
 
129
    result |= ((byte & 0x7f) << bit);
 
130
    bit += 7;
 
131
  } while (byte & 0x80);
 
132
  // sign extend negative numbers
 
133
  if ((byte & 0x40) != 0)
 
134
    result |= (-1LL) << bit;
 
135
  addr = (pint_t) p;
 
136
  return result;
 
137
}
 
138
 
 
139
inline LocalAddressSpace::pint_t LocalAddressSpace::getEncodedP(pint_t &addr,
 
140
                                                         pint_t end,
 
141
                                                         uint8_t encoding) {
 
142
  pint_t startAddr = addr;
 
143
  const uint8_t *p = (uint8_t *)addr;
 
144
  pint_t result;
 
145
 
 
146
  // first get value
 
147
  switch (encoding & 0x0F) {
 
148
  case DW_EH_PE_ptr:
 
149
    result = getP(addr);
 
150
    p += sizeof(pint_t);
 
151
    addr = (pint_t) p;
 
152
    break;
 
153
  case DW_EH_PE_uleb128:
 
154
    result = (pint_t)getULEB128(addr, end);
 
155
    break;
 
156
  case DW_EH_PE_udata2:
 
157
    result = get16(addr);
 
158
    p += 2;
 
159
    addr = (pint_t) p;
 
160
    break;
 
161
  case DW_EH_PE_udata4:
 
162
    result = get32(addr);
 
163
    p += 4;
 
164
    addr = (pint_t) p;
 
165
    break;
 
166
  case DW_EH_PE_udata8:
 
167
    result = (pint_t)get64(addr);
 
168
    p += 8;
 
169
    addr = (pint_t) p;
 
170
    break;
 
171
  case DW_EH_PE_sleb128:
 
172
    result = (pint_t)getSLEB128(addr, end);
 
173
    break;
 
174
  case DW_EH_PE_sdata2:
 
175
    result = (uint16_t)get16(addr);
 
176
    p += 2;
 
177
    addr = (pint_t) p;
 
178
    break;
 
179
  case DW_EH_PE_sdata4:
 
180
    result = (uint32_t)get32(addr);
 
181
    p += 4;
 
182
    addr = (pint_t) p;
 
183
    break;
 
184
  case DW_EH_PE_sdata8:
 
185
    result = (pint_t)get64(addr);
 
186
    p += 8;
 
187
    addr = (pint_t) p;
 
188
    break;
 
189
  default:
 
190
    _LIBUNWIND_ABORT("unknown pointer encoding");
 
191
  }
 
192
 
 
193
  // then add relative offset
 
194
  switch (encoding & 0x70) {
 
195
  case DW_EH_PE_absptr:
 
196
    // do nothing
 
197
    break;
 
198
  case DW_EH_PE_pcrel:
 
199
    result += startAddr;
 
200
    break;
 
201
  case DW_EH_PE_textrel:
 
202
    _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported");
 
203
    break;
 
204
  case DW_EH_PE_datarel:
 
205
    _LIBUNWIND_ABORT("DW_EH_PE_datarel pointer encoding not supported");
 
206
    break;
 
207
  case DW_EH_PE_funcrel:
 
208
    _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported");
 
209
    break;
 
210
  case DW_EH_PE_aligned:
 
211
    _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported");
 
212
    break;
 
213
  default:
 
214
    _LIBUNWIND_ABORT("unknown pointer encoding");
 
215
    break;
 
216
  }
 
217
 
 
218
  if (encoding & DW_EH_PE_indirect)
 
219
    result = getP(result);
 
220
 
 
221
  return result;
 
222
}
 
223
 
 
224
#if __APPLE__ 
 
225
  struct dyld_unwind_sections
 
226
  {
 
227
    const struct mach_header*   mh;
 
228
    const void*                 dwarf_section;
 
229
    uintptr_t                   dwarf_section_length;
 
230
    const void*                 compact_unwind_section;
 
231
    uintptr_t                   compact_unwind_section_length;
 
232
  };
 
233
  #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
 
234
                                  && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
 
235
    // In 10.7.0 or later, libSystem.dylib implements this function.
 
236
    extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
 
237
  #else
 
238
    // In 10.6.x and earlier, we need to implement this functionality.
 
239
    static inline bool _dyld_find_unwind_sections(void* addr, 
 
240
                                                    dyld_unwind_sections* info) {
 
241
      // Find mach-o image containing address.
 
242
      Dl_info dlinfo;
 
243
      if (!dladdr(addr, &dlinfo))
 
244
        return false;
 
245
      const mach_header *mh = (const mach_header *)dlinfo.dli_saddr;
 
246
      
 
247
      // Find dwarf unwind section in that image.
 
248
      unsigned long size;
 
249
      const uint8_t *p = getsectiondata(mh, "__TEXT", "__eh_frame", &size);
 
250
      if (!p)
 
251
        return false;
 
252
      
 
253
      // Fill in return struct.
 
254
      info->mh = mh;
 
255
      info->dwarf_section = p;
 
256
      info->dwarf_section_length = size;
 
257
      info->compact_unwind_section = 0;
 
258
      info->compact_unwind_section_length = 0;
 
259
     
 
260
      return true;
 
261
    }
 
262
  #endif
 
263
#endif
 
264
 
 
265
inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
 
266
                                                  UnwindInfoSections &info) {
 
267
#if __APPLE__
 
268
  dyld_unwind_sections dyldInfo;
 
269
  if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
 
270
    info.dso_base                      = (uintptr_t)dyldInfo.mh;
 
271
 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
 
272
    info.dwarf_section                 = (uintptr_t)dyldInfo.dwarf_section;
 
273
    info.dwarf_section_length          = dyldInfo.dwarf_section_length;
 
274
 #endif
 
275
    info.compact_unwind_section        = (uintptr_t)dyldInfo.compact_unwind_section;
 
276
    info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
 
277
    return true;
 
278
  }
 
279
#else
 
280
  // TO DO
 
281
 
 
282
#endif
 
283
 
 
284
  return false;
 
285
}
 
286
 
 
287
 
 
288
inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
 
289
#if __APPLE__
 
290
  return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde));
 
291
#else
 
292
  // TO DO: if OS has way to dynamically register FDEs, check that.
 
293
  return false;
 
294
#endif
 
295
}
 
296
 
 
297
inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
 
298
                                                size_t bufLen,
 
299
                                                unw_word_t *offset) {
 
300
  dl_info dyldInfo;
 
301
  if (dladdr((void *)addr, &dyldInfo)) {
 
302
    if (dyldInfo.dli_sname != NULL) {
 
303
      strlcpy(buf, dyldInfo.dli_sname, bufLen);
 
304
      *offset = (addr - (pint_t) dyldInfo.dli_saddr);
 
305
      return true;
 
306
    }
 
307
  }
 
308
  return false;
 
309
}
 
310
 
 
311
 
 
312
 
 
313
#if UNW_REMOTE
 
314
 
 
315
/// OtherAddressSpace is used as a template parameter to UnwindCursor when
 
316
/// unwinding a thread in the another process.  The other process can be a
 
317
/// different endianness and a different pointer size which is handled by
 
318
/// the P template parameter.
 
319
template <typename P>
 
320
class OtherAddressSpace {
 
321
public:
 
322
  OtherAddressSpace(task_t task) : fTask(task) {}
 
323
 
 
324
  typedef typename P::uint_t pint_t;
 
325
 
 
326
  uint8_t   get8(pint_t addr);
 
327
  uint16_t  get16(pint_t addr);
 
328
  uint32_t  get32(pint_t addr);
 
329
  uint64_t  get64(pint_t addr);
 
330
  pint_t    getP(pint_t addr);
 
331
  uint64_t  getULEB128(pint_t &addr, pint_t end);
 
332
  int64_t   getSLEB128(pint_t &addr, pint_t end);
 
333
  pint_t    getEncodedP(pint_t &addr, pint_t end, uint8_t encoding);
 
334
  bool      findFunctionName(pint_t addr, char *buf, size_t bufLen,
 
335
                        unw_word_t *offset);
 
336
  bool      findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
 
337
  bool      findOtherFDE(pint_t targetAddr, pint_t &fde);
 
338
private:
 
339
  void *localCopy(pint_t addr);
 
340
 
 
341
  task_t fTask;
 
342
};
 
343
 
 
344
template <typename P> uint8_t OtherAddressSpace<P>::get8(pint_t addr) {
 
345
  return *((uint8_t *)localCopy(addr));
 
346
}
 
347
 
 
348
template <typename P> uint16_t OtherAddressSpace<P>::get16(pint_t addr) {
 
349
  return P::E::get16(*(uint16_t *)localCopy(addr));
 
350
}
 
351
 
 
352
template <typename P> uint32_t OtherAddressSpace<P>::get32(pint_t addr) {
 
353
  return P::E::get32(*(uint32_t *)localCopy(addr));
 
354
}
 
355
 
 
356
template <typename P> uint64_t OtherAddressSpace<P>::get64(pint_t addr) {
 
357
  return P::E::get64(*(uint64_t *)localCopy(addr));
 
358
}
 
359
 
 
360
template <typename P>
 
361
typename P::uint_t OtherAddressSpace<P>::getP(pint_t addr) {
 
362
  return P::getP(*(uint64_t *)localCopy(addr));
 
363
}
 
364
 
 
365
template <typename P>
 
366
uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
 
367
  uintptr_t size = (end - addr);
 
368
  LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
 
369
  LocalAddressSpace::pint_t sladdr = laddr;
 
370
  uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size);
 
371
  addr += (laddr - sladdr);
 
372
  return result;
 
373
}
 
374
 
 
375
template <typename P>
 
376
int64_t OtherAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
 
377
  uintptr_t size = (end - addr);
 
378
  LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
 
379
  LocalAddressSpace::pint_t sladdr = laddr;
 
380
  uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size);
 
381
  addr += (laddr - sladdr);
 
382
  return result;
 
383
}
 
384
 
 
385
template <typename P> void *OtherAddressSpace<P>::localCopy(pint_t addr) {
 
386
  // FIX ME
 
387
}
 
388
 
 
389
template <typename P>
 
390
bool OtherAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
 
391
                                            size_t bufLen, unw_word_t *offset) {
 
392
  // FIX ME
 
393
}
 
394
 
 
395
/// unw_addr_space is the base class that abstract unw_addr_space_t type in
 
396
/// libunwind.h points to.
 
397
struct unw_addr_space {
 
398
  cpu_type_t cpuType;
 
399
  task_t taskPort;
 
400
};
 
401
 
 
402
/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points
 
403
/// to when examining
 
404
/// a 32-bit intel process.
 
405
struct unw_addr_space_i386 : public unw_addr_space {
 
406
  unw_addr_space_i386(task_t task) : oas(task) {}
 
407
  OtherAddressSpace<Pointer32<LittleEndian> > oas;
 
408
};
 
409
 
 
410
/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
 
411
/// points to when examining
 
412
/// a 64-bit intel process.
 
413
struct unw_addr_space_x86_64 : public unw_addr_space {
 
414
  unw_addr_space_x86_64(task_t task) : oas(task) {}
 
415
  OtherAddressSpace<Pointer64<LittleEndian> > oas;
 
416
};
 
417
 
 
418
/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
 
419
/// to when examining
 
420
/// a 32-bit PowerPC process.
 
421
struct unw_addr_space_ppc : public unw_addr_space {
 
422
  unw_addr_space_ppc(task_t task) : oas(task) {}
 
423
  OtherAddressSpace<Pointer32<BigEndian> > oas;
 
424
};
 
425
 
 
426
#endif // UNW_REMOTE
 
427
 
 
428
} // namespace libunwind
 
429
 
 
430
#endif // __ADDRESSSPACE_HPP__