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 typedef uintptr_t pint_t; 146 typedef intptr_t sint_t; 147 uint8_t get8(pint_t addr) { 148 uint8_t val; 149 memcpy(&val, (void *)addr, sizeof(val)); 150 return val; 151 } 152 uint16_t get16(pint_t addr) { 153 uint16_t val; 154 memcpy(&val, (void *)addr, sizeof(val)); 155 return val; 156 } 157 uint32_t get32(pint_t addr) { 158 uint32_t val; 159 memcpy(&val, (void *)addr, sizeof(val)); 160 return val; 161 } 162 uint64_t get64(pint_t addr) { 163 uint64_t val; 164 memcpy(&val, (void *)addr, sizeof(val)); 165 return val; 166 } 167 double getDouble(pint_t addr) { 168 double val; 169 memcpy(&val, (void *)addr, sizeof(val)); 170 return val; 171 } 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 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. 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. 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 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 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 // FIXME: This section name actually is truncated, ideally we 386 // should locate and check the full long name instead. 387 info.dwarf_section = begin; 388 info.dwarf_section_length = pish->Misc.VirtualSize; 389 found_hdr = true; 390 } 391 if (found_obj && found_hdr) 392 return true; 393 } 394 } 395 return false; 396 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) && \ 397 (__ANDROID_API__ < 21) 398 int length = 0; 399 info.arm_section = 400 (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); 401 info.arm_section_length = (uintptr_t)length; 402 if (info.arm_section && info.arm_section_length) 403 return true; 404 #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 405 struct dl_iterate_cb_data { 406 LocalAddressSpace *addressSpace; 407 UnwindInfoSections *sects; 408 uintptr_t targetAddr; 409 }; 410 411 dl_iterate_cb_data cb_data = {this, &info, targetAddr}; 412 int found = dl_iterate_phdr( 413 [](struct dl_phdr_info *pinfo, size_t, void *data) -> int { 414 auto cbdata = static_cast<dl_iterate_cb_data *>(data); 415 bool found_obj = false; 416 bool found_hdr = false; 417 418 assert(cbdata); 419 assert(cbdata->sects); 420 421 if (cbdata->targetAddr < pinfo->dlpi_addr) { 422 return false; 423 } 424 425 #if !defined(Elf_Half) 426 typedef ElfW(Half) Elf_Half; 427 #endif 428 #if !defined(Elf_Phdr) 429 typedef ElfW(Phdr) Elf_Phdr; 430 #endif 431 #if !defined(Elf_Addr) && defined(__ANDROID__) 432 typedef ElfW(Addr) Elf_Addr; 433 #endif 434 435 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 436 #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) 437 #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." 438 #endif 439 size_t object_length; 440 #if defined(__ANDROID__) 441 Elf_Addr image_base = 442 pinfo->dlpi_phnum 443 ? reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) - 444 reinterpret_cast<const Elf_Phdr *>(pinfo->dlpi_phdr) 445 ->p_offset 446 : 0; 447 #endif 448 449 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { 450 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; 451 if (phdr->p_type == PT_LOAD) { 452 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; 453 #if defined(__ANDROID__) 454 if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base) 455 begin = begin + image_base; 456 #endif 457 uintptr_t end = begin + phdr->p_memsz; 458 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { 459 cbdata->sects->dso_base = begin; 460 object_length = phdr->p_memsz; 461 found_obj = true; 462 } 463 } else if (phdr->p_type == PT_GNU_EH_FRAME) { 464 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; 465 uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr; 466 #if defined(__ANDROID__) 467 if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base) 468 eh_frame_hdr_start = eh_frame_hdr_start + image_base; 469 #endif 470 cbdata->sects->dwarf_index_section = eh_frame_hdr_start; 471 cbdata->sects->dwarf_index_section_length = phdr->p_memsz; 472 EHHeaderParser<LocalAddressSpace>::decodeEHHdr( 473 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, 474 hdrInfo); 475 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; 476 found_hdr = true; 477 } 478 } 479 480 if (found_obj && found_hdr) { 481 cbdata->sects->dwarf_section_length = object_length; 482 return true; 483 } else { 484 return false; 485 } 486 #else // defined(_LIBUNWIND_ARM_EHABI) 487 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { 488 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; 489 if (phdr->p_type == PT_LOAD) { 490 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; 491 uintptr_t end = begin + phdr->p_memsz; 492 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) 493 found_obj = true; 494 } else if (phdr->p_type == PT_ARM_EXIDX) { 495 uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr; 496 cbdata->sects->arm_section = exidx_start; 497 cbdata->sects->arm_section_length = phdr->p_memsz; 498 found_hdr = true; 499 } 500 } 501 return found_obj && found_hdr; 502 #endif 503 }, 504 &cb_data); 505 return static_cast<bool>(found); 506 #endif 507 508 return false; 509 } 510 511 512 inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { 513 #ifdef __APPLE__ 514 return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde)); 515 #else 516 // TO DO: if OS has way to dynamically register FDEs, check that. 517 (void)targetAddr; 518 (void)fde; 519 return false; 520 #endif 521 } 522 523 inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, 524 size_t bufLen, 525 unw_word_t *offset) { 526 #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) 527 Dl_info dyldInfo; 528 if (dladdr((void *)addr, &dyldInfo)) { 529 if (dyldInfo.dli_sname != NULL) { 530 snprintf(buf, bufLen, "%s", dyldInfo.dli_sname); 531 *offset = (addr - (pint_t) dyldInfo.dli_saddr); 532 return true; 533 } 534 } 535 #endif 536 return false; 537 } 538 539 540 541 #ifdef UNW_REMOTE 542 543 /// RemoteAddressSpace is used as a template parameter to UnwindCursor when 544 /// unwinding a thread in the another process. The other process can be a 545 /// different endianness and a different pointer size which is handled by 546 /// the P template parameter. 547 template <typename P> 548 class RemoteAddressSpace { 549 public: 550 RemoteAddressSpace(task_t task) : fTask(task) {} 551 552 typedef typename P::uint_t pint_t; 553 554 uint8_t get8(pint_t addr); 555 uint16_t get16(pint_t addr); 556 uint32_t get32(pint_t addr); 557 uint64_t get64(pint_t addr); 558 pint_t getP(pint_t addr); 559 uint64_t getULEB128(pint_t &addr, pint_t end); 560 int64_t getSLEB128(pint_t &addr, pint_t end); 561 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, 562 pint_t datarelBase = 0); 563 bool findFunctionName(pint_t addr, char *buf, size_t bufLen, 564 unw_word_t *offset); 565 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); 566 bool findOtherFDE(pint_t targetAddr, pint_t &fde); 567 private: 568 void *localCopy(pint_t addr); 569 570 task_t fTask; 571 }; 572 573 template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) { 574 return *((uint8_t *)localCopy(addr)); 575 } 576 577 template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) { 578 return P::E::get16(*(uint16_t *)localCopy(addr)); 579 } 580 581 template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) { 582 return P::E::get32(*(uint32_t *)localCopy(addr)); 583 } 584 585 template <typename P> uint64_t RemoteAddressSpace<P>::get64(pint_t addr) { 586 return P::E::get64(*(uint64_t *)localCopy(addr)); 587 } 588 589 template <typename P> 590 typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) { 591 return P::getP(*(uint64_t *)localCopy(addr)); 592 } 593 594 template <typename P> 595 uint64_t RemoteAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) { 596 uintptr_t size = (end - addr); 597 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); 598 LocalAddressSpace::pint_t sladdr = laddr; 599 uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size); 600 addr += (laddr - sladdr); 601 return result; 602 } 603 604 template <typename P> 605 int64_t RemoteAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) { 606 uintptr_t size = (end - addr); 607 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); 608 LocalAddressSpace::pint_t sladdr = laddr; 609 uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size); 610 addr += (laddr - sladdr); 611 return result; 612 } 613 614 template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) { 615 // FIX ME 616 } 617 618 template <typename P> 619 bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf, 620 size_t bufLen, 621 unw_word_t *offset) { 622 // FIX ME 623 } 624 625 /// unw_addr_space is the base class that abstract unw_addr_space_t type in 626 /// libunwind.h points to. 627 struct unw_addr_space { 628 cpu_type_t cpuType; 629 task_t taskPort; 630 }; 631 632 /// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points 633 /// to when examining 634 /// a 32-bit intel process. 635 struct unw_addr_space_i386 : public unw_addr_space { 636 unw_addr_space_i386(task_t task) : oas(task) {} 637 RemoteAddressSpace<Pointer32<LittleEndian>> oas; 638 }; 639 640 /// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t 641 /// points to when examining 642 /// a 64-bit intel process. 643 struct unw_addr_space_x86_64 : public unw_addr_space { 644 unw_addr_space_x86_64(task_t task) : oas(task) {} 645 RemoteAddressSpace<Pointer64<LittleEndian>> oas; 646 }; 647 648 /// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points 649 /// to when examining 650 /// a 32-bit PowerPC process. 651 struct unw_addr_space_ppc : public unw_addr_space { 652 unw_addr_space_ppc(task_t task) : oas(task) {} 653 RemoteAddressSpace<Pointer32<BigEndian>> oas; 654 }; 655 656 #endif // UNW_REMOTE 657 658 } // namespace libunwind 659 660 #endif // __ADDRESSSPACE_HPP__ 661