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). 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 #ifdef __LP64__ 146 typedef uint64_t pint_t; 147 typedef int64_t sint_t; 148 #else 149 typedef uint32_t pint_t; 150 typedef int32_t sint_t; 151 #endif 152 uint8_t get8(pint_t addr) { 153 uint8_t val; 154 memcpy(&val, (void *)addr, sizeof(val)); 155 return val; 156 } 157 uint16_t get16(pint_t addr) { 158 uint16_t val; 159 memcpy(&val, (void *)addr, sizeof(val)); 160 return val; 161 } 162 uint32_t get32(pint_t addr) { 163 uint32_t val; 164 memcpy(&val, (void *)addr, sizeof(val)); 165 return val; 166 } 167 uint64_t get64(pint_t addr) { 168 uint64_t val; 169 memcpy(&val, (void *)addr, sizeof(val)); 170 return val; 171 } 172 double getDouble(pint_t addr) { 173 double val; 174 memcpy(&val, (void *)addr, sizeof(val)); 175 return val; 176 } 177 v128 getVector(pint_t addr) { 178 v128 val; 179 memcpy(&val, (void *)addr, sizeof(val)); 180 return val; 181 } 182 uintptr_t getP(pint_t addr); 183 static uint64_t getULEB128(pint_t &addr, pint_t end); 184 static int64_t getSLEB128(pint_t &addr, pint_t end); 185 186 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, 187 pint_t datarelBase = 0); 188 bool findFunctionName(pint_t addr, char *buf, size_t bufLen, 189 unw_word_t *offset); 190 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); 191 bool findOtherFDE(pint_t targetAddr, pint_t &fde); 192 193 static LocalAddressSpace sThisAddressSpace; 194 }; 195 196 inline uintptr_t LocalAddressSpace::getP(pint_t addr) { 197 #ifdef __LP64__ 198 return get64(addr); 199 #else 200 return get32(addr); 201 #endif 202 } 203 204 /// Read a ULEB128 into a 64-bit word. 205 inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) { 206 const uint8_t *p = (uint8_t *)addr; 207 const uint8_t *pend = (uint8_t *)end; 208 uint64_t result = 0; 209 int bit = 0; 210 do { 211 uint64_t b; 212 213 if (p == pend) 214 _LIBUNWIND_ABORT("truncated uleb128 expression"); 215 216 b = *p & 0x7f; 217 218 if (bit >= 64 || b << bit >> bit != b) { 219 _LIBUNWIND_ABORT("malformed uleb128 expression"); 220 } else { 221 result |= b << bit; 222 bit += 7; 223 } 224 } while (*p++ >= 0x80); 225 addr = (pint_t) p; 226 return result; 227 } 228 229 /// Read a SLEB128 into a 64-bit word. 230 inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { 231 const uint8_t *p = (uint8_t *)addr; 232 const uint8_t *pend = (uint8_t *)end; 233 int64_t result = 0; 234 int bit = 0; 235 uint8_t byte; 236 do { 237 if (p == pend) 238 _LIBUNWIND_ABORT("truncated sleb128 expression"); 239 byte = *p++; 240 result |= ((byte & 0x7f) << bit); 241 bit += 7; 242 } while (byte & 0x80); 243 // sign extend negative numbers 244 if ((byte & 0x40) != 0) 245 result |= (-1ULL) << bit; 246 addr = (pint_t) p; 247 return result; 248 } 249 250 inline LocalAddressSpace::pint_t 251 LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, 252 pint_t datarelBase) { 253 pint_t startAddr = addr; 254 const uint8_t *p = (uint8_t *)addr; 255 pint_t result; 256 257 // first get value 258 switch (encoding & 0x0F) { 259 case DW_EH_PE_ptr: 260 result = getP(addr); 261 p += sizeof(pint_t); 262 addr = (pint_t) p; 263 break; 264 case DW_EH_PE_uleb128: 265 result = (pint_t)getULEB128(addr, end); 266 break; 267 case DW_EH_PE_udata2: 268 result = get16(addr); 269 p += 2; 270 addr = (pint_t) p; 271 break; 272 case DW_EH_PE_udata4: 273 result = get32(addr); 274 p += 4; 275 addr = (pint_t) p; 276 break; 277 case DW_EH_PE_udata8: 278 result = (pint_t)get64(addr); 279 p += 8; 280 addr = (pint_t) p; 281 break; 282 case DW_EH_PE_sleb128: 283 result = (pint_t)getSLEB128(addr, end); 284 break; 285 case DW_EH_PE_sdata2: 286 // Sign extend from signed 16-bit value. 287 result = (pint_t)(int16_t)get16(addr); 288 p += 2; 289 addr = (pint_t) p; 290 break; 291 case DW_EH_PE_sdata4: 292 // Sign extend from signed 32-bit value. 293 result = (pint_t)(int32_t)get32(addr); 294 p += 4; 295 addr = (pint_t) p; 296 break; 297 case DW_EH_PE_sdata8: 298 result = (pint_t)get64(addr); 299 p += 8; 300 addr = (pint_t) p; 301 break; 302 default: 303 _LIBUNWIND_ABORT("unknown pointer encoding"); 304 } 305 306 // then add relative offset 307 switch (encoding & 0x70) { 308 case DW_EH_PE_absptr: 309 // do nothing 310 break; 311 case DW_EH_PE_pcrel: 312 result += startAddr; 313 break; 314 case DW_EH_PE_textrel: 315 _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported"); 316 break; 317 case DW_EH_PE_datarel: 318 // DW_EH_PE_datarel is only valid in a few places, so the parameter has a 319 // default value of 0, and we abort in the event that someone calls this 320 // function with a datarelBase of 0 and DW_EH_PE_datarel encoding. 321 if (datarelBase == 0) 322 _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0"); 323 result += datarelBase; 324 break; 325 case DW_EH_PE_funcrel: 326 _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported"); 327 break; 328 case DW_EH_PE_aligned: 329 _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported"); 330 break; 331 default: 332 _LIBUNWIND_ABORT("unknown pointer encoding"); 333 break; 334 } 335 336 if (encoding & DW_EH_PE_indirect) 337 result = getP(result); 338 339 return result; 340 } 341 342 inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, 343 UnwindInfoSections &info) { 344 #ifdef __APPLE__ 345 dyld_unwind_sections dyldInfo; 346 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { 347 info.dso_base = (uintptr_t)dyldInfo.mh; 348 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 349 info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section; 350 info.dwarf_section_length = dyldInfo.dwarf_section_length; 351 #endif 352 info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section; 353 info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length; 354 return true; 355 } 356 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) 357 // Bare metal is statically linked, so no need to ask the dynamic loader 358 info.arm_section = (uintptr_t)(&__exidx_start); 359 info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start); 360 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x", 361 info.arm_section, info.arm_section_length); 362 if (info.arm_section && info.arm_section_length) 363 return true; 364 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) 365 HMODULE mods[1024]; 366 HANDLE process = GetCurrentProcess(); 367 DWORD needed; 368 369 if (!EnumProcessModules(process, mods, sizeof(mods), &needed)) 370 return false; 371 372 for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) { 373 PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i]; 374 PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew); 375 PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader; 376 PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh); 377 bool found_obj = false; 378 bool found_hdr = false; 379 380 info.dso_base = (uintptr_t)mods[i]; 381 for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) { 382 uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i]; 383 uintptr_t end = begin + pish->Misc.VirtualSize; 384 if (!strncmp((const char *)pish->Name, ".text", 385 IMAGE_SIZEOF_SHORT_NAME)) { 386 if (targetAddr >= begin && targetAddr < end) 387 found_obj = true; 388 } else if (!strncmp((const char *)pish->Name, ".eh_frame", 389 IMAGE_SIZEOF_SHORT_NAME)) { 390 // FIXME: This section name actually is truncated, ideally we 391 // should locate and check the full long name instead. 392 info.dwarf_section = begin; 393 info.dwarf_section_length = pish->Misc.VirtualSize; 394 found_hdr = true; 395 } 396 if (found_obj && found_hdr) 397 return true; 398 } 399 } 400 return false; 401 #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 402 struct dl_iterate_cb_data { 403 LocalAddressSpace *addressSpace; 404 UnwindInfoSections *sects; 405 uintptr_t targetAddr; 406 }; 407 408 dl_iterate_cb_data cb_data = {this, &info, targetAddr}; 409 int found = dl_iterate_phdr( 410 [](struct dl_phdr_info *pinfo, size_t, void *data) -> int { 411 auto cbdata = static_cast<dl_iterate_cb_data *>(data); 412 bool found_obj = false; 413 bool found_hdr = false; 414 415 assert(cbdata); 416 assert(cbdata->sects); 417 418 if (cbdata->targetAddr < pinfo->dlpi_addr) { 419 return false; 420 } 421 422 #if !defined(Elf_Half) 423 typedef ElfW(Half) Elf_Half; 424 #endif 425 #if !defined(Elf_Phdr) 426 typedef ElfW(Phdr) Elf_Phdr; 427 #endif 428 #if !defined(Elf_Addr) && defined(__ANDROID__) 429 typedef ElfW(Addr) Elf_Addr; 430 #endif 431 432 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 433 #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) 434 #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." 435 #endif 436 size_t object_length; 437 #if defined(__ANDROID__) 438 Elf_Addr image_base = 439 pinfo->dlpi_phnum 440 ? reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) - 441 reinterpret_cast<const Elf_Phdr *>(pinfo->dlpi_phdr) 442 ->p_offset 443 : 0; 444 #endif 445 446 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { 447 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; 448 if (phdr->p_type == PT_LOAD) { 449 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; 450 #if defined(__ANDROID__) 451 if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base) 452 begin = begin + image_base; 453 #endif 454 uintptr_t end = begin + phdr->p_memsz; 455 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { 456 cbdata->sects->dso_base = begin; 457 object_length = phdr->p_memsz; 458 found_obj = true; 459 } 460 } else if (phdr->p_type == PT_GNU_EH_FRAME) { 461 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; 462 uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr; 463 #if defined(__ANDROID__) 464 if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base) 465 eh_frame_hdr_start = eh_frame_hdr_start + image_base; 466 #endif 467 cbdata->sects->dwarf_index_section = eh_frame_hdr_start; 468 cbdata->sects->dwarf_index_section_length = phdr->p_memsz; 469 EHHeaderParser<LocalAddressSpace>::decodeEHHdr( 470 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, 471 hdrInfo); 472 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; 473 found_hdr = true; 474 } 475 } 476 477 if (found_obj && found_hdr) { 478 cbdata->sects->dwarf_section_length = object_length; 479 return true; 480 } else { 481 return false; 482 } 483 #else // defined(_LIBUNWIND_ARM_EHABI) 484 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { 485 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; 486 if (phdr->p_type == PT_LOAD) { 487 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; 488 uintptr_t end = begin + phdr->p_memsz; 489 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) 490 found_obj = true; 491 } else if (phdr->p_type == PT_ARM_EXIDX) { 492 uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr; 493 cbdata->sects->arm_section = exidx_start; 494 cbdata->sects->arm_section_length = phdr->p_memsz; 495 found_hdr = true; 496 } 497 } 498 return found_obj && found_hdr; 499 #endif 500 }, 501 &cb_data); 502 return static_cast<bool>(found); 503 #endif 504 505 return false; 506 } 507 508 509 inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { 510 #ifdef __APPLE__ 511 return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde)); 512 #else 513 // TO DO: if OS has way to dynamically register FDEs, check that. 514 (void)targetAddr; 515 (void)fde; 516 return false; 517 #endif 518 } 519 520 inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, 521 size_t bufLen, 522 unw_word_t *offset) { 523 #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) 524 Dl_info dyldInfo; 525 if (dladdr((void *)addr, &dyldInfo)) { 526 if (dyldInfo.dli_sname != NULL) { 527 snprintf(buf, bufLen, "%s", dyldInfo.dli_sname); 528 *offset = (addr - (pint_t) dyldInfo.dli_saddr); 529 return true; 530 } 531 } 532 #endif 533 return false; 534 } 535 536 537 538 #ifdef UNW_REMOTE 539 540 /// RemoteAddressSpace is used as a template parameter to UnwindCursor when 541 /// unwinding a thread in the another process. The other process can be a 542 /// different endianness and a different pointer size which is handled by 543 /// the P template parameter. 544 template <typename P> 545 class RemoteAddressSpace { 546 public: 547 RemoteAddressSpace(task_t task) : fTask(task) {} 548 549 typedef typename P::uint_t pint_t; 550 551 uint8_t get8(pint_t addr); 552 uint16_t get16(pint_t addr); 553 uint32_t get32(pint_t addr); 554 uint64_t get64(pint_t addr); 555 pint_t getP(pint_t addr); 556 uint64_t getULEB128(pint_t &addr, pint_t end); 557 int64_t getSLEB128(pint_t &addr, pint_t end); 558 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, 559 pint_t datarelBase = 0); 560 bool findFunctionName(pint_t addr, char *buf, size_t bufLen, 561 unw_word_t *offset); 562 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); 563 bool findOtherFDE(pint_t targetAddr, pint_t &fde); 564 private: 565 void *localCopy(pint_t addr); 566 567 task_t fTask; 568 }; 569 570 template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) { 571 return *((uint8_t *)localCopy(addr)); 572 } 573 574 template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) { 575 return P::E::get16(*(uint16_t *)localCopy(addr)); 576 } 577 578 template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) { 579 return P::E::get32(*(uint32_t *)localCopy(addr)); 580 } 581 582 template <typename P> uint64_t RemoteAddressSpace<P>::get64(pint_t addr) { 583 return P::E::get64(*(uint64_t *)localCopy(addr)); 584 } 585 586 template <typename P> 587 typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) { 588 return P::getP(*(uint64_t *)localCopy(addr)); 589 } 590 591 template <typename P> 592 uint64_t RemoteAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) { 593 uintptr_t size = (end - addr); 594 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); 595 LocalAddressSpace::pint_t sladdr = laddr; 596 uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size); 597 addr += (laddr - sladdr); 598 return result; 599 } 600 601 template <typename P> 602 int64_t RemoteAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) { 603 uintptr_t size = (end - addr); 604 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); 605 LocalAddressSpace::pint_t sladdr = laddr; 606 uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size); 607 addr += (laddr - sladdr); 608 return result; 609 } 610 611 template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) { 612 // FIX ME 613 } 614 615 template <typename P> 616 bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf, 617 size_t bufLen, 618 unw_word_t *offset) { 619 // FIX ME 620 } 621 622 /// unw_addr_space is the base class that abstract unw_addr_space_t type in 623 /// libunwind.h points to. 624 struct unw_addr_space { 625 cpu_type_t cpuType; 626 task_t taskPort; 627 }; 628 629 /// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points 630 /// to when examining 631 /// a 32-bit intel process. 632 struct unw_addr_space_i386 : public unw_addr_space { 633 unw_addr_space_i386(task_t task) : oas(task) {} 634 RemoteAddressSpace<Pointer32<LittleEndian>> oas; 635 }; 636 637 /// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t 638 /// points to when examining 639 /// a 64-bit intel process. 640 struct unw_addr_space_x86_64 : public unw_addr_space { 641 unw_addr_space_x86_64(task_t task) : oas(task) {} 642 RemoteAddressSpace<Pointer64<LittleEndian>> oas; 643 }; 644 645 /// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points 646 /// to when examining 647 /// a 32-bit PowerPC process. 648 struct unw_addr_space_ppc : public unw_addr_space { 649 unw_addr_space_ppc(task_t task) : oas(task) {} 650 RemoteAddressSpace<Pointer32<BigEndian>> oas; 651 }; 652 653 #endif // UNW_REMOTE 654 655 } // namespace libunwind 656 657 #endif // __ADDRESSSPACE_HPP__ 658