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 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 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 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: 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 571 template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) { 572 return *((uint8_t *)localCopy(addr)); 573 } 574 575 template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) { 576 return P::E::get16(*(uint16_t *)localCopy(addr)); 577 } 578 579 template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) { 580 return P::E::get32(*(uint32_t *)localCopy(addr)); 581 } 582 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> 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> 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> 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 612 template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) { 613 // FIX ME 614 } 615 616 template <typename P> 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 { 634 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 { 642 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 { 650 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