blob: f804a85dabac707d83c2db265238e632de4194e4 [file] [log] [blame]
Saleem Abdulrasool675df582015-04-24 19:39:17 +00001//===------------------------- 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#ifndef _LIBUNWIND_IS_BAREMETAL
22#include <dlfcn.h>
23#endif
24
25#ifdef __APPLE__
26#include <mach-o/getsect.h>
27namespace 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"
Ed Schouten98340812017-03-07 18:21:51 +000035#include "EHHeaderParser.hpp"
Saleem Abdulrasool675df582015-04-24 19:39:17 +000036#include "Registers.hpp"
37
Saleem Abdulrasool675df582015-04-24 19:39:17 +000038namespace libunwind {
39
40/// Used by findUnwindSections() to return info about needed sections.
41struct UnwindInfoSections {
42#if _LIBUNWIND_SUPPORT_DWARF_UNWIND || _LIBUNWIND_SUPPORT_DWARF_INDEX || \
43 _LIBUNWIND_SUPPORT_COMPACT_UNWIND
44 // No dso_base for ARM EHABI.
45 uintptr_t dso_base;
46#endif
47#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
48 uintptr_t dwarf_section;
49 uintptr_t dwarf_section_length;
50#endif
51#if _LIBUNWIND_SUPPORT_DWARF_INDEX
52 uintptr_t dwarf_index_section;
53 uintptr_t dwarf_index_section_length;
54#endif
55#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
56 uintptr_t compact_unwind_section;
57 uintptr_t compact_unwind_section_length;
58#endif
Logan Chien61278582015-07-19 15:23:10 +000059#if _LIBUNWIND_ARM_EHABI
Saleem Abdulrasool675df582015-04-24 19:39:17 +000060 uintptr_t arm_section;
61 uintptr_t arm_section_length;
62#endif
63};
64
65
66/// LocalAddressSpace is used as a template parameter to UnwindCursor when
67/// unwinding a thread in the same process. The wrappers compile away,
68/// making local unwinds fast.
69class __attribute__((visibility("hidden"))) LocalAddressSpace {
70public:
71#ifdef __LP64__
72 typedef uint64_t pint_t;
73 typedef int64_t sint_t;
74#else
75 typedef uint32_t pint_t;
76 typedef int32_t sint_t;
77#endif
78 uint8_t get8(pint_t addr) {
79 uint8_t val;
80 memcpy(&val, (void *)addr, sizeof(val));
81 return val;
82 }
83 uint16_t get16(pint_t addr) {
84 uint16_t val;
85 memcpy(&val, (void *)addr, sizeof(val));
86 return val;
87 }
88 uint32_t get32(pint_t addr) {
89 uint32_t val;
90 memcpy(&val, (void *)addr, sizeof(val));
91 return val;
92 }
93 uint64_t get64(pint_t addr) {
94 uint64_t val;
95 memcpy(&val, (void *)addr, sizeof(val));
96 return val;
97 }
98 double getDouble(pint_t addr) {
99 double val;
100 memcpy(&val, (void *)addr, sizeof(val));
101 return val;
102 }
103 v128 getVector(pint_t addr) {
104 v128 val;
105 memcpy(&val, (void *)addr, sizeof(val));
106 return val;
107 }
108 uintptr_t getP(pint_t addr);
109 static uint64_t getULEB128(pint_t &addr, pint_t end);
110 static int64_t getSLEB128(pint_t &addr, pint_t end);
111
112 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
113 pint_t datarelBase = 0);
114 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
115 unw_word_t *offset);
116 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
117 bool findOtherFDE(pint_t targetAddr, pint_t &fde);
118
119 static LocalAddressSpace sThisAddressSpace;
120};
121
122inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
123#ifdef __LP64__
124 return get64(addr);
125#else
126 return get32(addr);
127#endif
128}
129
130/// Read a ULEB128 into a 64-bit word.
131inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
132 const uint8_t *p = (uint8_t *)addr;
133 const uint8_t *pend = (uint8_t *)end;
134 uint64_t result = 0;
135 int bit = 0;
136 do {
137 uint64_t b;
138
139 if (p == pend)
140 _LIBUNWIND_ABORT("truncated uleb128 expression");
141
142 b = *p & 0x7f;
143
144 if (bit >= 64 || b << bit >> bit != b) {
145 _LIBUNWIND_ABORT("malformed uleb128 expression");
146 } else {
147 result |= b << bit;
148 bit += 7;
149 }
150 } while (*p++ >= 0x80);
151 addr = (pint_t) p;
152 return result;
153}
154
155/// Read a SLEB128 into a 64-bit word.
156inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
157 const uint8_t *p = (uint8_t *)addr;
158 const uint8_t *pend = (uint8_t *)end;
159 int64_t result = 0;
160 int bit = 0;
161 uint8_t byte;
162 do {
163 if (p == pend)
164 _LIBUNWIND_ABORT("truncated sleb128 expression");
165 byte = *p++;
166 result |= ((byte & 0x7f) << bit);
167 bit += 7;
168 } while (byte & 0x80);
169 // sign extend negative numbers
170 if ((byte & 0x40) != 0)
171 result |= (-1LL) << bit;
172 addr = (pint_t) p;
173 return result;
174}
175
176inline LocalAddressSpace::pint_t
177LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
178 pint_t datarelBase) {
179 pint_t startAddr = addr;
180 const uint8_t *p = (uint8_t *)addr;
181 pint_t result;
182
183 // first get value
184 switch (encoding & 0x0F) {
185 case DW_EH_PE_ptr:
186 result = getP(addr);
187 p += sizeof(pint_t);
188 addr = (pint_t) p;
189 break;
190 case DW_EH_PE_uleb128:
191 result = (pint_t)getULEB128(addr, end);
192 break;
193 case DW_EH_PE_udata2:
194 result = get16(addr);
195 p += 2;
196 addr = (pint_t) p;
197 break;
198 case DW_EH_PE_udata4:
199 result = get32(addr);
200 p += 4;
201 addr = (pint_t) p;
202 break;
203 case DW_EH_PE_udata8:
204 result = (pint_t)get64(addr);
205 p += 8;
206 addr = (pint_t) p;
207 break;
208 case DW_EH_PE_sleb128:
209 result = (pint_t)getSLEB128(addr, end);
210 break;
211 case DW_EH_PE_sdata2:
212 // Sign extend from signed 16-bit value.
213 result = (pint_t)(int16_t)get16(addr);
214 p += 2;
215 addr = (pint_t) p;
216 break;
217 case DW_EH_PE_sdata4:
218 // Sign extend from signed 32-bit value.
219 result = (pint_t)(int32_t)get32(addr);
220 p += 4;
221 addr = (pint_t) p;
222 break;
223 case DW_EH_PE_sdata8:
224 result = (pint_t)get64(addr);
225 p += 8;
226 addr = (pint_t) p;
227 break;
228 default:
229 _LIBUNWIND_ABORT("unknown pointer encoding");
230 }
231
232 // then add relative offset
233 switch (encoding & 0x70) {
234 case DW_EH_PE_absptr:
235 // do nothing
236 break;
237 case DW_EH_PE_pcrel:
238 result += startAddr;
239 break;
240 case DW_EH_PE_textrel:
241 _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported");
242 break;
243 case DW_EH_PE_datarel:
244 // DW_EH_PE_datarel is only valid in a few places, so the parameter has a
245 // default value of 0, and we abort in the event that someone calls this
246 // function with a datarelBase of 0 and DW_EH_PE_datarel encoding.
247 if (datarelBase == 0)
248 _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0");
249 result += datarelBase;
250 break;
251 case DW_EH_PE_funcrel:
252 _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported");
253 break;
254 case DW_EH_PE_aligned:
255 _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported");
256 break;
257 default:
258 _LIBUNWIND_ABORT("unknown pointer encoding");
259 break;
260 }
261
262 if (encoding & DW_EH_PE_indirect)
263 result = getP(result);
264
265 return result;
266}
267
268#ifdef __APPLE__
Ed Schouten4b0ff4e2017-03-07 18:15:52 +0000269
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000270 struct dyld_unwind_sections
271 {
272 const struct mach_header* mh;
273 const void* dwarf_section;
274 uintptr_t dwarf_section_length;
275 const void* compact_unwind_section;
276 uintptr_t compact_unwind_section_length;
277 };
278 #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
279 && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \
280 || defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
281 // In 10.7.0 or later, libSystem.dylib implements this function.
282 extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
283 #else
Nick Kledzikb109e942016-10-31 21:04:17 +0000284 // In 10.6.x and earlier, we need to implement this functionality. Note
285 // that this requires a newer version of libmacho (from cctools) than is
286 // present in libSystem on 10.6.x (for getsectiondata).
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000287 static inline bool _dyld_find_unwind_sections(void* addr,
288 dyld_unwind_sections* info) {
289 // Find mach-o image containing address.
290 Dl_info dlinfo;
291 if (!dladdr(addr, &dlinfo))
292 return false;
Nick Kledzikb109e942016-10-31 21:04:17 +0000293#if __LP64__
294 const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase;
295#else
296 const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase;
297#endif
298
299 // Initialize the return struct
300 info->mh = (const struct mach_header *)mh;
301 info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length);
302 info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length);
303
304 if (!info->dwarf_section) {
305 info->dwarf_section_length = 0;
306 }
307
308 if (!info->compact_unwind_section) {
309 info->compact_unwind_section_length = 0;
310 }
311
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000312 return true;
313 }
314 #endif
Ed Schouten4b0ff4e2017-03-07 18:15:52 +0000315
316#elif _LIBUNWIND_ARM_EHABI && defined(_LIBUNWIND_IS_BAREMETAL)
317
318// When statically linked on bare-metal, the symbols for the EH table are looked
319// up without going through the dynamic loader.
320extern char __exidx_start;
321extern char __exidx_end;
322
323#elif _LIBUNWIND_ARM_EHABI || _LIBUNWIND_SUPPORT_DWARF_UNWIND
324
325// ELF-based systems may use dl_iterate_phdr() to access sections
326// containing unwinding information. The ElfW() macro for pointer-size
327// independent ELF header traversal is not provided by <link.h> on some
328// systems (e.g., FreeBSD). On these systems the data structures are
329// just called Elf_XXX. Define ElfW() locally.
330#include <link.h>
331#if !defined(ElfW)
332#define ElfW(type) Elf_##type
333#endif
334
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000335#endif
336
337inline 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 _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 }
Ed Schouten1b650c92017-03-05 19:11:24 +0000351#elif _LIBUNWIND_ARM_EHABI && defined(_LIBUNWIND_IS_BAREMETAL)
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000352 // 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);
Ed Masteadc29082016-08-30 15:38:10 +0000355 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x",
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000356 info.arm_section, info.arm_section_length);
357 if (info.arm_section && info.arm_section_length)
358 return true;
Ed Schouten1b650c92017-03-05 19:11:24 +0000359#elif _LIBUNWIND_ARM_EHABI || _LIBUNWIND_SUPPORT_DWARF_UNWIND
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000360 struct dl_iterate_cb_data {
361 LocalAddressSpace *addressSpace;
362 UnwindInfoSections *sects;
363 uintptr_t targetAddr;
364 };
365
366 dl_iterate_cb_data cb_data = {this, &info, targetAddr};
367 int found = dl_iterate_phdr(
368 [](struct dl_phdr_info *pinfo, size_t, void *data) -> int {
369 auto cbdata = static_cast<dl_iterate_cb_data *>(data);
Ed Schouten50bddc12017-02-23 09:13:22 +0000370 bool found_obj = false;
371 bool found_hdr = false;
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000372
373 assert(cbdata);
374 assert(cbdata->sects);
375
376 if (cbdata->targetAddr < pinfo->dlpi_addr) {
377 return false;
378 }
379
Viktor Kutuzov9ed9c3b2015-05-06 10:32:28 +0000380#if !defined(Elf_Half)
381 typedef ElfW(Half) Elf_Half;
382#endif
383#if !defined(Elf_Phdr)
384 typedef ElfW(Phdr) Elf_Phdr;
385#endif
386
Ed Schouten1b650c92017-03-05 19:11:24 +0000387 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
388 #if !_LIBUNWIND_SUPPORT_DWARF_INDEX
389 #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
390 #endif
391 size_t object_length;
Viktor Kutuzov9ed9c3b2015-05-06 10:32:28 +0000392 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
393 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000394 if (phdr->p_type == PT_LOAD) {
395 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
396 uintptr_t end = begin + phdr->p_memsz;
397 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) {
398 cbdata->sects->dso_base = begin;
399 object_length = phdr->p_memsz;
400 found_obj = true;
401 }
402 } else if (phdr->p_type == PT_GNU_EH_FRAME) {
403 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
404 uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr;
405 cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
406 cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
407 EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
408 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
409 hdrInfo);
410 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
411 found_hdr = true;
412 }
413 }
414
415 if (found_obj && found_hdr) {
416 cbdata->sects->dwarf_section_length = object_length;
417 return true;
418 } else {
419 return false;
420 }
Ed Schouten1b650c92017-03-05 19:11:24 +0000421 #else // _LIBUNWIND_ARM_EHABI
422 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
423 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
424 if (phdr->p_type == PT_LOAD) {
425 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
426 uintptr_t end = begin + phdr->p_memsz;
427 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end)
428 found_obj = true;
429 } else if (phdr->p_type == PT_ARM_EXIDX) {
430 uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr;
431 cbdata->sects->arm_section = exidx_start;
Ed Schouten99794722017-03-07 15:21:57 +0000432 cbdata->sects->arm_section_length = phdr->p_memsz;
Ed Schouten1b650c92017-03-05 19:11:24 +0000433 found_hdr = true;
434 }
435 }
436 return found_obj && found_hdr;
437 #endif
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000438 },
439 &cb_data);
440 return static_cast<bool>(found);
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000441#endif
442
443 return false;
444}
445
446
447inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
448#ifdef __APPLE__
449 return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde));
450#else
451 // TO DO: if OS has way to dynamically register FDEs, check that.
452 (void)targetAddr;
453 (void)fde;
454 return false;
455#endif
456}
457
458inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
459 size_t bufLen,
460 unw_word_t *offset) {
461#ifndef _LIBUNWIND_IS_BAREMETAL
462 Dl_info dyldInfo;
463 if (dladdr((void *)addr, &dyldInfo)) {
464 if (dyldInfo.dli_sname != NULL) {
465 snprintf(buf, bufLen, "%s", dyldInfo.dli_sname);
466 *offset = (addr - (pint_t) dyldInfo.dli_saddr);
467 return true;
468 }
469 }
470#endif
471 return false;
472}
473
474
475
476#ifdef UNW_REMOTE
477
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000478/// RemoteAddressSpace is used as a template parameter to UnwindCursor when
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000479/// unwinding a thread in the another process. The other process can be a
480/// different endianness and a different pointer size which is handled by
481/// the P template parameter.
482template <typename P>
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000483class RemoteAddressSpace {
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000484public:
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000485 RemoteAddressSpace(task_t task) : fTask(task) {}
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000486
487 typedef typename P::uint_t pint_t;
488
489 uint8_t get8(pint_t addr);
490 uint16_t get16(pint_t addr);
491 uint32_t get32(pint_t addr);
492 uint64_t get64(pint_t addr);
493 pint_t getP(pint_t addr);
494 uint64_t getULEB128(pint_t &addr, pint_t end);
495 int64_t getSLEB128(pint_t &addr, pint_t end);
496 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
497 pint_t datarelBase = 0);
498 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
499 unw_word_t *offset);
500 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
501 bool findOtherFDE(pint_t targetAddr, pint_t &fde);
502private:
503 void *localCopy(pint_t addr);
504
505 task_t fTask;
506};
507
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000508template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000509 return *((uint8_t *)localCopy(addr));
510}
511
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000512template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000513 return P::E::get16(*(uint16_t *)localCopy(addr));
514}
515
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000516template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000517 return P::E::get32(*(uint32_t *)localCopy(addr));
518}
519
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000520template <typename P> uint64_t RemoteAddressSpace<P>::get64(pint_t addr) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000521 return P::E::get64(*(uint64_t *)localCopy(addr));
522}
523
524template <typename P>
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000525typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000526 return P::getP(*(uint64_t *)localCopy(addr));
527}
528
529template <typename P>
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000530uint64_t RemoteAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000531 uintptr_t size = (end - addr);
532 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
533 LocalAddressSpace::pint_t sladdr = laddr;
534 uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size);
535 addr += (laddr - sladdr);
536 return result;
537}
538
539template <typename P>
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000540int64_t RemoteAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000541 uintptr_t size = (end - addr);
542 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
543 LocalAddressSpace::pint_t sladdr = laddr;
544 uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size);
545 addr += (laddr - sladdr);
546 return result;
547}
548
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000549template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000550 // FIX ME
551}
552
553template <typename P>
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000554bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
555 size_t bufLen,
556 unw_word_t *offset) {
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000557 // FIX ME
558}
559
560/// unw_addr_space is the base class that abstract unw_addr_space_t type in
561/// libunwind.h points to.
562struct unw_addr_space {
563 cpu_type_t cpuType;
564 task_t taskPort;
565};
566
567/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points
568/// to when examining
569/// a 32-bit intel process.
570struct unw_addr_space_i386 : public unw_addr_space {
571 unw_addr_space_i386(task_t task) : oas(task) {}
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000572 RemoteAddressSpace<Pointer32<LittleEndian>> oas;
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000573};
574
575/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
576/// points to when examining
577/// a 64-bit intel process.
578struct unw_addr_space_x86_64 : public unw_addr_space {
579 unw_addr_space_x86_64(task_t task) : oas(task) {}
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000580 RemoteAddressSpace<Pointer64<LittleEndian>> oas;
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000581};
582
583/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
584/// to when examining
585/// a 32-bit PowerPC process.
586struct unw_addr_space_ppc : public unw_addr_space {
587 unw_addr_space_ppc(task_t task) : oas(task) {}
Saleem Abdulrasoolfa054682017-01-21 16:22:46 +0000588 RemoteAddressSpace<Pointer32<BigEndian>> oas;
Saleem Abdulrasool675df582015-04-24 19:39:17 +0000589};
590
591#endif // UNW_REMOTE
592
593} // namespace libunwind
594
595#endif // __ADDRESSSPACE_HPP__