blob: 2ed52a5583c2e4b0e7112ec7cce5a0c3a7b9b93c [file] [log] [blame]
Saleem Abdulrasool17552662015-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 Schoutenda7d6252017-03-07 18:21:51 +000035#include "EHHeaderParser.hpp"
Saleem Abdulrasool17552662015-04-24 19:39:17 +000036#include "Registers.hpp"
37
Saleem Abdulrasool17552662015-04-24 19:39:17 +000038namespace libunwind {
39
40/// Used by findUnwindSections() to return info about needed sections.
41struct UnwindInfoSections {
Ranjeet Singh421231a2017-03-31 15:28:06 +000042#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \
43 defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +000044 // No dso_base for ARM EHABI.
45 uintptr_t dso_base;
46#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +000047#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +000048 uintptr_t dwarf_section;
49 uintptr_t dwarf_section_length;
50#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +000051#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
Saleem Abdulrasool17552662015-04-24 19:39:17 +000052 uintptr_t dwarf_index_section;
53 uintptr_t dwarf_index_section_length;
54#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +000055#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +000056 uintptr_t compact_unwind_section;
57 uintptr_t compact_unwind_section_length;
58#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +000059#if defined(_LIBUNWIND_ARM_EHABI)
Saleem Abdulrasool17552662015-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)
Marshall Clowa6d7c382017-06-21 16:02:53 +0000171 result |= (-1ULL) << bit;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000172 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
Marshall Clowa6d7c382017-06-21 16:02:53 +0000268#ifdef __APPLE__
Ed Schouten600e5462017-03-07 18:15:52 +0000269
Saleem Abdulrasool17552662015-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 Kledzik9c56de12016-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).
Marshall Clowa6d7c382017-06-21 16:02:53 +0000287 static inline bool _dyld_find_unwind_sections(void* addr,
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000288 dyld_unwind_sections* info) {
289 // Find mach-o image containing address.
290 Dl_info dlinfo;
291 if (!dladdr(addr, &dlinfo))
292 return false;
Nick Kledzik9c56de12016-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 Abdulrasool17552662015-04-24 19:39:17 +0000312 return true;
313 }
314 #endif
Ed Schouten600e5462017-03-07 18:15:52 +0000315
Ranjeet Singh421231a2017-03-31 15:28:06 +0000316#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
Ed Schouten600e5462017-03-07 18:15:52 +0000317
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
Ranjeet Singh421231a2017-03-31 15:28:06 +0000323#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Ed Schouten600e5462017-03-07 18:15:52 +0000324
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 Abdulrasool17552662015-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;
Ranjeet Singh421231a2017-03-31 15:28:06 +0000343 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000344 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 }
Ranjeet Singh421231a2017-03-31 15:28:06 +0000351#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
Saleem Abdulrasool17552662015-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 Maste41bc5a72016-08-30 15:38:10 +0000355 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x",
Saleem Abdulrasool17552662015-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;
Ranjeet Singh421231a2017-03-31 15:28:06 +0000359#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-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 Schouten08032ee2017-02-23 09:13:22 +0000370 bool found_obj = false;
371 bool found_hdr = false;
Saleem Abdulrasool17552662015-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 Kutuzova28f5b32015-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
Ivan Krasind34d77f2017-04-06 17:35:35 +0000386#if !defined(Elf_Addr) && defined(__ANDROID__)
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000387 typedef ElfW(Addr) Elf_Addr;
388#endif
Viktor Kutuzova28f5b32015-05-06 10:32:28 +0000389
Ranjeet Singh421231a2017-03-31 15:28:06 +0000390 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
391 #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
Ed Schouten6a4939b2017-03-05 19:11:24 +0000392 #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
393 #endif
394 size_t object_length;
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000395#if defined(__ANDROID__)
396 Elf_Addr image_base =
Saleem Abdulrasoole4fe5f92017-04-05 21:29:38 +0000397 pinfo->dlpi_phnum
398 ? reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) -
399 reinterpret_cast<const Elf_Phdr *>(pinfo->dlpi_phdr)
400 ->p_offset
401 : 0;
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000402#endif
403
Viktor Kutuzova28f5b32015-05-06 10:32:28 +0000404 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
405 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000406 if (phdr->p_type == PT_LOAD) {
407 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000408#if defined(__ANDROID__)
409 if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
410 begin = begin + image_base;
411#endif
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000412 uintptr_t end = begin + phdr->p_memsz;
413 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) {
414 cbdata->sects->dso_base = begin;
415 object_length = phdr->p_memsz;
416 found_obj = true;
417 }
418 } else if (phdr->p_type == PT_GNU_EH_FRAME) {
419 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
420 uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr;
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000421#if defined(__ANDROID__)
422 if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
423 eh_frame_hdr_start = eh_frame_hdr_start + image_base;
424#endif
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000425 cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
426 cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
427 EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
428 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
429 hdrInfo);
430 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
431 found_hdr = true;
432 }
433 }
434
435 if (found_obj && found_hdr) {
436 cbdata->sects->dwarf_section_length = object_length;
437 return true;
438 } else {
439 return false;
440 }
Ranjeet Singh421231a2017-03-31 15:28:06 +0000441 #else // defined(_LIBUNWIND_ARM_EHABI)
Ed Schouten6a4939b2017-03-05 19:11:24 +0000442 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
443 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
444 if (phdr->p_type == PT_LOAD) {
445 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
446 uintptr_t end = begin + phdr->p_memsz;
447 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end)
448 found_obj = true;
449 } else if (phdr->p_type == PT_ARM_EXIDX) {
450 uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr;
451 cbdata->sects->arm_section = exidx_start;
Ed Schouten5d3f35b2017-03-07 15:21:57 +0000452 cbdata->sects->arm_section_length = phdr->p_memsz;
Ed Schouten6a4939b2017-03-05 19:11:24 +0000453 found_hdr = true;
454 }
455 }
456 return found_obj && found_hdr;
457 #endif
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000458 },
459 &cb_data);
460 return static_cast<bool>(found);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000461#endif
462
463 return false;
464}
465
466
467inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
468#ifdef __APPLE__
469 return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde));
470#else
471 // TO DO: if OS has way to dynamically register FDEs, check that.
472 (void)targetAddr;
473 (void)fde;
474 return false;
475#endif
476}
477
478inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
479 size_t bufLen,
480 unw_word_t *offset) {
481#ifndef _LIBUNWIND_IS_BAREMETAL
482 Dl_info dyldInfo;
483 if (dladdr((void *)addr, &dyldInfo)) {
484 if (dyldInfo.dli_sname != NULL) {
485 snprintf(buf, bufLen, "%s", dyldInfo.dli_sname);
486 *offset = (addr - (pint_t) dyldInfo.dli_saddr);
487 return true;
488 }
489 }
490#endif
491 return false;
492}
493
494
495
496#ifdef UNW_REMOTE
497
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000498/// RemoteAddressSpace is used as a template parameter to UnwindCursor when
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000499/// unwinding a thread in the another process. The other process can be a
500/// different endianness and a different pointer size which is handled by
501/// the P template parameter.
502template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000503class RemoteAddressSpace {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000504public:
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000505 RemoteAddressSpace(task_t task) : fTask(task) {}
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000506
507 typedef typename P::uint_t pint_t;
508
509 uint8_t get8(pint_t addr);
510 uint16_t get16(pint_t addr);
511 uint32_t get32(pint_t addr);
512 uint64_t get64(pint_t addr);
513 pint_t getP(pint_t addr);
514 uint64_t getULEB128(pint_t &addr, pint_t end);
515 int64_t getSLEB128(pint_t &addr, pint_t end);
516 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
517 pint_t datarelBase = 0);
518 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
519 unw_word_t *offset);
520 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
521 bool findOtherFDE(pint_t targetAddr, pint_t &fde);
522private:
523 void *localCopy(pint_t addr);
524
525 task_t fTask;
526};
527
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000528template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000529 return *((uint8_t *)localCopy(addr));
530}
531
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000532template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000533 return P::E::get16(*(uint16_t *)localCopy(addr));
534}
535
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000536template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000537 return P::E::get32(*(uint32_t *)localCopy(addr));
538}
539
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000540template <typename P> uint64_t RemoteAddressSpace<P>::get64(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000541 return P::E::get64(*(uint64_t *)localCopy(addr));
542}
543
544template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000545typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000546 return P::getP(*(uint64_t *)localCopy(addr));
547}
548
549template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000550uint64_t RemoteAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000551 uintptr_t size = (end - addr);
552 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
553 LocalAddressSpace::pint_t sladdr = laddr;
554 uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size);
555 addr += (laddr - sladdr);
556 return result;
557}
558
559template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000560int64_t RemoteAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000561 uintptr_t size = (end - addr);
562 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
563 LocalAddressSpace::pint_t sladdr = laddr;
564 uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size);
565 addr += (laddr - sladdr);
566 return result;
567}
568
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000569template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000570 // FIX ME
571}
572
573template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000574bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
575 size_t bufLen,
576 unw_word_t *offset) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000577 // FIX ME
578}
579
580/// unw_addr_space is the base class that abstract unw_addr_space_t type in
581/// libunwind.h points to.
582struct unw_addr_space {
583 cpu_type_t cpuType;
584 task_t taskPort;
585};
586
587/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points
588/// to when examining
589/// a 32-bit intel process.
590struct unw_addr_space_i386 : public unw_addr_space {
591 unw_addr_space_i386(task_t task) : oas(task) {}
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000592 RemoteAddressSpace<Pointer32<LittleEndian>> oas;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000593};
594
595/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
596/// points to when examining
597/// a 64-bit intel process.
598struct unw_addr_space_x86_64 : public unw_addr_space {
599 unw_addr_space_x86_64(task_t task) : oas(task) {}
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000600 RemoteAddressSpace<Pointer64<LittleEndian>> oas;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000601};
602
603/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
604/// to when examining
605/// a 32-bit PowerPC process.
606struct unw_addr_space_ppc : public unw_addr_space {
607 unw_addr_space_ppc(task_t task) : oas(task) {}
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000608 RemoteAddressSpace<Pointer32<BigEndian>> oas;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000609};
610
611#endif // UNW_REMOTE
612
613} // namespace libunwind
614
615#endif // __ADDRESSSPACE_HPP__