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 <string.h>
20 
21 #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
22 #include <dlfcn.h>
23 #endif
24 
25 #ifdef __APPLE__
26 #include <mach-o/getsect.h>
27 namespace libunwind {
28    bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde);
29 }
30 #endif
31 
32 #include "libunwind.h"
33 #include "config.h"
34 #include "dwarf2.h"
35 #include "EHHeaderParser.hpp"
36 #include "Registers.hpp"
37 
38 #ifdef __APPLE__
39 
40   struct dyld_unwind_sections
41   {
42     const struct mach_header*   mh;
43     const void*                 dwarf_section;
44     uintptr_t                   dwarf_section_length;
45     const void*                 compact_unwind_section;
46     uintptr_t                   compact_unwind_section_length;
47   };
48   #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
49                                  && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \
50       || defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
51     // In 10.7.0 or later, libSystem.dylib implements this function.
52     extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
53   #else
54     // In 10.6.x and earlier, we need to implement this functionality. Note
55     // that this requires a newer version of libmacho (from cctools) than is
56     // present in libSystem on 10.6.x (for getsectiondata).
_dyld_find_unwind_sections(void * addr,dyld_unwind_sections * info)57     static inline bool _dyld_find_unwind_sections(void* addr,
58                                                     dyld_unwind_sections* info) {
59       // Find mach-o image containing address.
60       Dl_info dlinfo;
61       if (!dladdr(addr, &dlinfo))
62         return false;
63 #if __LP64__
64       const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase;
65 #else
66       const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase;
67 #endif
68 
69       // Initialize the return struct
70       info->mh = (const struct mach_header *)mh;
71       info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length);
72       info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length);
73 
74       if (!info->dwarf_section) {
75         info->dwarf_section_length = 0;
76       }
77 
78       if (!info->compact_unwind_section) {
79         info->compact_unwind_section_length = 0;
80       }
81 
82       return true;
83     }
84   #endif
85 
86 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
87 
88 // When statically linked on bare-metal, the symbols for the EH table are looked
89 // up without going through the dynamic loader.
90 extern char __exidx_start;
91 extern char __exidx_end;
92 
93 #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
94 
95 // ELF-based systems may use dl_iterate_phdr() to access sections
96 // containing unwinding information. The ElfW() macro for pointer-size
97 // independent ELF header traversal is not provided by <link.h> on some
98 // systems (e.g., FreeBSD). On these systems the data structures are
99 // just called Elf_XXX. Define ElfW() locally.
100 #ifndef _WIN32
101 #include <link.h>
102 #else
103 #include <windows.h>
104 #include <psapi.h>
105 #endif
106 #if !defined(ElfW)
107 #define ElfW(type) Elf_##type
108 #endif
109 
110 #endif
111 
112 namespace libunwind {
113 
114 /// Used by findUnwindSections() to return info about needed sections.
115 struct UnwindInfoSections {
116 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) ||       \
117     defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
118   // No dso_base for ARM EHABI.
119   uintptr_t       dso_base;
120 #endif
121 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
122   uintptr_t       dwarf_section;
123   uintptr_t       dwarf_section_length;
124 #endif
125 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
126   uintptr_t       dwarf_index_section;
127   uintptr_t       dwarf_index_section_length;
128 #endif
129 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
130   uintptr_t       compact_unwind_section;
131   uintptr_t       compact_unwind_section_length;
132 #endif
133 #if defined(_LIBUNWIND_ARM_EHABI)
134   uintptr_t       arm_section;
135   uintptr_t       arm_section_length;
136 #endif
137 };
138 
139 
140 /// LocalAddressSpace is used as a template parameter to UnwindCursor when
141 /// unwinding a thread in the same process.  The wrappers compile away,
142 /// making local unwinds fast.
143 class __attribute__((visibility("hidden"))) LocalAddressSpace {
144 public:
145   typedef uintptr_t pint_t;
146   typedef intptr_t  sint_t;
get8(pint_t addr)147   uint8_t         get8(pint_t addr) {
148     uint8_t val;
149     memcpy(&val, (void *)addr, sizeof(val));
150     return val;
151   }
get16(pint_t addr)152   uint16_t         get16(pint_t addr) {
153     uint16_t val;
154     memcpy(&val, (void *)addr, sizeof(val));
155     return val;
156   }
get32(pint_t addr)157   uint32_t         get32(pint_t addr) {
158     uint32_t val;
159     memcpy(&val, (void *)addr, sizeof(val));
160     return val;
161   }
get64(pint_t addr)162   uint64_t         get64(pint_t addr) {
163     uint64_t val;
164     memcpy(&val, (void *)addr, sizeof(val));
165     return val;
166   }
getDouble(pint_t addr)167   double           getDouble(pint_t addr) {
168     double val;
169     memcpy(&val, (void *)addr, sizeof(val));
170     return val;
171   }
getVector(pint_t addr)172   v128             getVector(pint_t addr) {
173     v128 val;
174     memcpy(&val, (void *)addr, sizeof(val));
175     return val;
176   }
177   uintptr_t       getP(pint_t addr);
178   static uint64_t getULEB128(pint_t &addr, pint_t end);
179   static int64_t  getSLEB128(pint_t &addr, pint_t end);
180 
181   pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
182                      pint_t datarelBase = 0);
183   bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
184                         unw_word_t *offset);
185   bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
186   bool findOtherFDE(pint_t targetAddr, pint_t &fde);
187 
188   static LocalAddressSpace sThisAddressSpace;
189 };
190 
getP(pint_t addr)191 inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
192 #if __SIZEOF_POINTER__ == 8
193   return get64(addr);
194 #else
195   return get32(addr);
196 #endif
197 }
198 
199 /// Read a ULEB128 into a 64-bit word.
getULEB128(pint_t & addr,pint_t end)200 inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
201   const uint8_t *p = (uint8_t *)addr;
202   const uint8_t *pend = (uint8_t *)end;
203   uint64_t result = 0;
204   int bit = 0;
205   do {
206     uint64_t b;
207 
208     if (p == pend)
209       _LIBUNWIND_ABORT("truncated uleb128 expression");
210 
211     b = *p & 0x7f;
212 
213     if (bit >= 64 || b << bit >> bit != b) {
214       _LIBUNWIND_ABORT("malformed uleb128 expression");
215     } else {
216       result |= b << bit;
217       bit += 7;
218     }
219   } while (*p++ >= 0x80);
220   addr = (pint_t) p;
221   return result;
222 }
223 
224 /// Read a SLEB128 into a 64-bit word.
getSLEB128(pint_t & addr,pint_t end)225 inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
226   const uint8_t *p = (uint8_t *)addr;
227   const uint8_t *pend = (uint8_t *)end;
228   int64_t result = 0;
229   int bit = 0;
230   uint8_t byte;
231   do {
232     if (p == pend)
233       _LIBUNWIND_ABORT("truncated sleb128 expression");
234     byte = *p++;
235     result |= ((byte & 0x7f) << bit);
236     bit += 7;
237   } while (byte & 0x80);
238   // sign extend negative numbers
239   if ((byte & 0x40) != 0)
240     result |= (-1ULL) << bit;
241   addr = (pint_t) p;
242   return result;
243 }
244 
245 inline LocalAddressSpace::pint_t
getEncodedP(pint_t & addr,pint_t end,uint8_t encoding,pint_t datarelBase)246 LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
247                                pint_t datarelBase) {
248   pint_t startAddr = addr;
249   const uint8_t *p = (uint8_t *)addr;
250   pint_t result;
251 
252   // first get value
253   switch (encoding & 0x0F) {
254   case DW_EH_PE_ptr:
255     result = getP(addr);
256     p += sizeof(pint_t);
257     addr = (pint_t) p;
258     break;
259   case DW_EH_PE_uleb128:
260     result = (pint_t)getULEB128(addr, end);
261     break;
262   case DW_EH_PE_udata2:
263     result = get16(addr);
264     p += 2;
265     addr = (pint_t) p;
266     break;
267   case DW_EH_PE_udata4:
268     result = get32(addr);
269     p += 4;
270     addr = (pint_t) p;
271     break;
272   case DW_EH_PE_udata8:
273     result = (pint_t)get64(addr);
274     p += 8;
275     addr = (pint_t) p;
276     break;
277   case DW_EH_PE_sleb128:
278     result = (pint_t)getSLEB128(addr, end);
279     break;
280   case DW_EH_PE_sdata2:
281     // Sign extend from signed 16-bit value.
282     result = (pint_t)(int16_t)get16(addr);
283     p += 2;
284     addr = (pint_t) p;
285     break;
286   case DW_EH_PE_sdata4:
287     // Sign extend from signed 32-bit value.
288     result = (pint_t)(int32_t)get32(addr);
289     p += 4;
290     addr = (pint_t) p;
291     break;
292   case DW_EH_PE_sdata8:
293     result = (pint_t)get64(addr);
294     p += 8;
295     addr = (pint_t) p;
296     break;
297   default:
298     _LIBUNWIND_ABORT("unknown pointer encoding");
299   }
300 
301   // then add relative offset
302   switch (encoding & 0x70) {
303   case DW_EH_PE_absptr:
304     // do nothing
305     break;
306   case DW_EH_PE_pcrel:
307     result += startAddr;
308     break;
309   case DW_EH_PE_textrel:
310     _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported");
311     break;
312   case DW_EH_PE_datarel:
313     // DW_EH_PE_datarel is only valid in a few places, so the parameter has a
314     // default value of 0, and we abort in the event that someone calls this
315     // function with a datarelBase of 0 and DW_EH_PE_datarel encoding.
316     if (datarelBase == 0)
317       _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0");
318     result += datarelBase;
319     break;
320   case DW_EH_PE_funcrel:
321     _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported");
322     break;
323   case DW_EH_PE_aligned:
324     _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported");
325     break;
326   default:
327     _LIBUNWIND_ABORT("unknown pointer encoding");
328     break;
329   }
330 
331   if (encoding & DW_EH_PE_indirect)
332     result = getP(result);
333 
334   return result;
335 }
336 
findUnwindSections(pint_t targetAddr,UnwindInfoSections & info)337 inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
338                                                   UnwindInfoSections &info) {
339 #ifdef __APPLE__
340   dyld_unwind_sections dyldInfo;
341   if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
342     info.dso_base                      = (uintptr_t)dyldInfo.mh;
343  #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
344     info.dwarf_section                 = (uintptr_t)dyldInfo.dwarf_section;
345     info.dwarf_section_length          = dyldInfo.dwarf_section_length;
346  #endif
347     info.compact_unwind_section        = (uintptr_t)dyldInfo.compact_unwind_section;
348     info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
349     return true;
350   }
351 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
352   // Bare metal is statically linked, so no need to ask the dynamic loader
353   info.arm_section =        (uintptr_t)(&__exidx_start);
354   info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start);
355   _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x",
356                              info.arm_section, info.arm_section_length);
357   if (info.arm_section && info.arm_section_length)
358     return true;
359 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
360   HMODULE mods[1024];
361   HANDLE process = GetCurrentProcess();
362   DWORD needed;
363 
364   if (!EnumProcessModules(process, mods, sizeof(mods), &needed))
365     return false;
366 
367   for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) {
368     PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i];
369     PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew);
370     PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
371     PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh);
372     bool found_obj = false;
373     bool found_hdr = false;
374 
375     info.dso_base = (uintptr_t)mods[i];
376     for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) {
377       uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i];
378       uintptr_t end = begin + pish->Misc.VirtualSize;
379       if (!strncmp((const char *)pish->Name, ".text",
380                    IMAGE_SIZEOF_SHORT_NAME)) {
381         if (targetAddr >= begin && targetAddr < end)
382           found_obj = true;
383       } else if (!strncmp((const char *)pish->Name, ".eh_frame",
384                           IMAGE_SIZEOF_SHORT_NAME)) {
385         info.dwarf_section = begin;
386         info.dwarf_section_length = pish->Misc.VirtualSize;
387         found_hdr = true;
388       }
389       if (found_obj && found_hdr)
390         return true;
391     }
392   }
393   return false;
394 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) &&                  \
395     (__ANDROID_API__ < 21)
396   int length = 0;
397   info.arm_section =
398       (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length);
399   info.arm_section_length = (uintptr_t)length;
400   if (info.arm_section && info.arm_section_length)
401     return true;
402 #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
403   struct dl_iterate_cb_data {
404     LocalAddressSpace *addressSpace;
405     UnwindInfoSections *sects;
406     uintptr_t targetAddr;
407   };
408 
409   dl_iterate_cb_data cb_data = {this, &info, targetAddr};
410   int found = dl_iterate_phdr(
411       [](struct dl_phdr_info *pinfo, size_t, void *data) -> int {
412         auto cbdata = static_cast<dl_iterate_cb_data *>(data);
413         bool found_obj = false;
414         bool found_hdr = false;
415 
416         assert(cbdata);
417         assert(cbdata->sects);
418 
419         if (cbdata->targetAddr < pinfo->dlpi_addr) {
420           return false;
421         }
422 
423 #if !defined(Elf_Half)
424         typedef ElfW(Half) Elf_Half;
425 #endif
426 #if !defined(Elf_Phdr)
427         typedef ElfW(Phdr) Elf_Phdr;
428 #endif
429 #if !defined(Elf_Addr) && defined(__ANDROID__)
430         typedef ElfW(Addr) Elf_Addr;
431 #endif
432 
433  #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
434   #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
435    #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
436   #endif
437         size_t object_length;
438 #if defined(__ANDROID__)
439         Elf_Addr image_base =
440             pinfo->dlpi_phnum
441                 ? reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) -
442                       reinterpret_cast<const Elf_Phdr *>(pinfo->dlpi_phdr)
443                           ->p_offset
444                 : 0;
445 #endif
446 
447         for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
448           const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
449           if (phdr->p_type == PT_LOAD) {
450             uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
451 #if defined(__ANDROID__)
452             if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
453               begin = begin + image_base;
454 #endif
455             uintptr_t end = begin + phdr->p_memsz;
456             if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) {
457               cbdata->sects->dso_base = begin;
458               object_length = phdr->p_memsz;
459               found_obj = true;
460             }
461           } else if (phdr->p_type == PT_GNU_EH_FRAME) {
462             EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
463             uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr;
464 #if defined(__ANDROID__)
465             if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
466               eh_frame_hdr_start = eh_frame_hdr_start + image_base;
467 #endif
468             cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
469             cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
470             EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
471                 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
472                 hdrInfo);
473             cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
474             found_hdr = true;
475           }
476         }
477 
478         if (found_obj && found_hdr) {
479           cbdata->sects->dwarf_section_length = object_length;
480           return true;
481         } else {
482           return false;
483         }
484  #else // defined(_LIBUNWIND_ARM_EHABI)
485         for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
486           const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
487           if (phdr->p_type == PT_LOAD) {
488             uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
489             uintptr_t end = begin + phdr->p_memsz;
490             if (cbdata->targetAddr >= begin && cbdata->targetAddr < end)
491               found_obj = true;
492           } else if (phdr->p_type == PT_ARM_EXIDX) {
493             uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr;
494             cbdata->sects->arm_section = exidx_start;
495             cbdata->sects->arm_section_length = phdr->p_memsz;
496             found_hdr = true;
497           }
498         }
499         return found_obj && found_hdr;
500  #endif
501       },
502       &cb_data);
503   return static_cast<bool>(found);
504 #endif
505 
506   return false;
507 }
508 
509 
findOtherFDE(pint_t targetAddr,pint_t & fde)510 inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
511 #ifdef __APPLE__
512   return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde));
513 #else
514   // TO DO: if OS has way to dynamically register FDEs, check that.
515   (void)targetAddr;
516   (void)fde;
517   return false;
518 #endif
519 }
520 
findFunctionName(pint_t addr,char * buf,size_t bufLen,unw_word_t * offset)521 inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
522                                                 size_t bufLen,
523                                                 unw_word_t *offset) {
524 #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
525   Dl_info dyldInfo;
526   if (dladdr((void *)addr, &dyldInfo)) {
527     if (dyldInfo.dli_sname != NULL) {
528       snprintf(buf, bufLen, "%s", dyldInfo.dli_sname);
529       *offset = (addr - (pint_t) dyldInfo.dli_saddr);
530       return true;
531     }
532   }
533 #endif
534   return false;
535 }
536 
537 
538 
539 #ifdef UNW_REMOTE
540 
541 /// RemoteAddressSpace is used as a template parameter to UnwindCursor when
542 /// unwinding a thread in the another process.  The other process can be a
543 /// different endianness and a different pointer size which is handled by
544 /// the P template parameter.
545 template <typename P>
546 class RemoteAddressSpace {
547 public:
RemoteAddressSpace(task_t task)548   RemoteAddressSpace(task_t task) : fTask(task) {}
549 
550   typedef typename P::uint_t pint_t;
551 
552   uint8_t   get8(pint_t addr);
553   uint16_t  get16(pint_t addr);
554   uint32_t  get32(pint_t addr);
555   uint64_t  get64(pint_t addr);
556   pint_t    getP(pint_t addr);
557   uint64_t  getULEB128(pint_t &addr, pint_t end);
558   int64_t   getSLEB128(pint_t &addr, pint_t end);
559   pint_t    getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
560                         pint_t datarelBase = 0);
561   bool      findFunctionName(pint_t addr, char *buf, size_t bufLen,
562                         unw_word_t *offset);
563   bool      findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
564   bool      findOtherFDE(pint_t targetAddr, pint_t &fde);
565 private:
566   void *localCopy(pint_t addr);
567 
568   task_t fTask;
569 };
570 
get8(pint_t addr)571 template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) {
572   return *((uint8_t *)localCopy(addr));
573 }
574 
get16(pint_t addr)575 template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) {
576   return P::E::get16(*(uint16_t *)localCopy(addr));
577 }
578 
get32(pint_t addr)579 template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) {
580   return P::E::get32(*(uint32_t *)localCopy(addr));
581 }
582 
get64(pint_t addr)583 template <typename P> uint64_t RemoteAddressSpace<P>::get64(pint_t addr) {
584   return P::E::get64(*(uint64_t *)localCopy(addr));
585 }
586 
587 template <typename P>
getP(pint_t addr)588 typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) {
589   return P::getP(*(uint64_t *)localCopy(addr));
590 }
591 
592 template <typename P>
getULEB128(pint_t & addr,pint_t end)593 uint64_t RemoteAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
594   uintptr_t size = (end - addr);
595   LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
596   LocalAddressSpace::pint_t sladdr = laddr;
597   uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size);
598   addr += (laddr - sladdr);
599   return result;
600 }
601 
602 template <typename P>
getSLEB128(pint_t & addr,pint_t end)603 int64_t RemoteAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
604   uintptr_t size = (end - addr);
605   LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
606   LocalAddressSpace::pint_t sladdr = laddr;
607   uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size);
608   addr += (laddr - sladdr);
609   return result;
610 }
611 
localCopy(pint_t addr)612 template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) {
613   // FIX ME
614 }
615 
616 template <typename P>
findFunctionName(pint_t addr,char * buf,size_t bufLen,unw_word_t * offset)617 bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
618                                              size_t bufLen,
619                                              unw_word_t *offset) {
620   // FIX ME
621 }
622 
623 /// unw_addr_space is the base class that abstract unw_addr_space_t type in
624 /// libunwind.h points to.
625 struct unw_addr_space {
626   cpu_type_t cpuType;
627   task_t taskPort;
628 };
629 
630 /// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points
631 /// to when examining
632 /// a 32-bit intel process.
633 struct unw_addr_space_i386 : public unw_addr_space {
unw_addr_space_i386libunwind::unw_addr_space_i386634   unw_addr_space_i386(task_t task) : oas(task) {}
635   RemoteAddressSpace<Pointer32<LittleEndian>> oas;
636 };
637 
638 /// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
639 /// points to when examining
640 /// a 64-bit intel process.
641 struct unw_addr_space_x86_64 : public unw_addr_space {
unw_addr_space_x86_64libunwind::unw_addr_space_x86_64642   unw_addr_space_x86_64(task_t task) : oas(task) {}
643   RemoteAddressSpace<Pointer64<LittleEndian>> oas;
644 };
645 
646 /// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
647 /// to when examining
648 /// a 32-bit PowerPC process.
649 struct unw_addr_space_ppc : public unw_addr_space {
unw_addr_space_ppclibunwind::unw_addr_space_ppc650   unw_addr_space_ppc(task_t task) : oas(task) {}
651   RemoteAddressSpace<Pointer32<BigEndian>> oas;
652 };
653 
654 #endif // UNW_REMOTE
655 
656 } // namespace libunwind
657 
658 #endif // __ADDRESSSPACE_HPP__
659