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 !_LIBUNWIND_IS_BAREMETAL 22 #include <dlfcn.h> 23 #if defined(__ANDROID__) && !__LP64__ 24 // dladdr only exits in API >= 8. Call to our my_dladdr in android/support for dynamic lookup 25 #if __ANDROID_API__ < 8 26 typedef struct { 27 const char *dli_fname; /* Pathname of shared object that contains address */ 28 void *dli_fbase; /* Address at which shared object is loaded */ 29 const char *dli_sname; /* Name of nearest symbol with address lower than addr */ 30 void *dli_saddr; /* Exact address of symbol named in dli_sname */ 31 } Dl_info; 32 #endif // __ANDROID_API__ >= 8 33 extern "C" int my_dladdr(const void* addr, Dl_info *info); 34 #define dladdr my_dladdr 35 #endif 36 #endif 37 38 #if __APPLE__ 39 #include <mach-o/getsect.h> 40 namespace libunwind { 41 bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde); 42 } 43 #endif 44 45 #include "libunwind.h" 46 #include "config.h" 47 #include "dwarf2.h" 48 #include "Registers.hpp" 49 50 #if LIBCXXABI_ARM_EHABI 51 #if __LINUX__ 52 // Emulate the BSD dl_unwind_find_exidx API when on a GNU libdl system. 53 typedef long unsigned int *_Unwind_Ptr; 54 extern "C" _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr targetAddr, int *length); 55 _Unwind_Ptr (*dl_unwind_find_exidx)(_Unwind_Ptr targetAddr, int *length) = 56 __gnu_Unwind_Find_exidx; 57 #else 58 #include <link.h> 59 #endif 60 #endif // LIBCXXABI_ARM_EHABI 61 62 #if LIBCXXABI_ARM_EHABI && _LIBUNWIND_IS_BAREMETAL 63 // When statically linked on bare-metal, the symbols for the EH table are looked 64 // up without going through the dynamic loader. 65 // TODO(jroelofs): since Newlib on arm-none-eabi doesn't 66 // have dl_unwind_find_exidx... 67 struct EHTEntry { 68 uint32_t functionOffset; 69 uint32_t unwindOpcodes; 70 }; 71 extern EHTEntry __exidx_start; 72 extern EHTEntry __exidx_end; 73 #endif 74 75 namespace libunwind { 76 77 /// Used by findUnwindSections() to return info about needed sections. 78 struct UnwindInfoSections { 79 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND 80 uintptr_t dso_base; 81 uintptr_t dwarf_section; 82 uintptr_t dwarf_section_length; 83 #endif 84 #if _LIBUNWIND_SUPPORT_DWARF_INDEX 85 uintptr_t dso_base; 86 uintptr_t dwarf_index_section; 87 uintptr_t dwarf_index_section_length; 88 #endif 89 #if _LIBUNWIND_SUPPORT_COMPACT_UNWIND 90 uintptr_t dso_base; 91 uintptr_t compact_unwind_section; 92 uintptr_t compact_unwind_section_length; 93 #endif 94 #if LIBCXXABI_ARM_EHABI 95 // No dso_base for ARM EHABI. 96 uintptr_t arm_section; 97 uintptr_t arm_section_length; 98 #endif 99 }; 100 101 102 /// LocalAddressSpace is used as a template parameter to UnwindCursor when 103 /// unwinding a thread in the same process. The wrappers compile away, 104 /// making local unwinds fast. 105 class __attribute__((visibility("hidden"))) LocalAddressSpace { 106 public: 107 #if __LP64__ 108 typedef uint64_t pint_t; 109 typedef int64_t sint_t; 110 #else 111 typedef uint32_t pint_t; 112 typedef int32_t sint_t; 113 #endif 114 uint8_t get8(pint_t addr) { 115 uint8_t val; 116 memcpy(&val, (void *)addr, sizeof(val)); 117 return val; 118 } 119 uint16_t get16(pint_t addr) { 120 uint16_t val; 121 memcpy(&val, (void *)addr, sizeof(val)); 122 return val; 123 } 124 uint32_t get32(pint_t addr) { 125 uint32_t val; 126 memcpy(&val, (void *)addr, sizeof(val)); 127 return val; 128 } 129 uint64_t get64(pint_t addr) { 130 uint64_t val; 131 memcpy(&val, (void *)addr, sizeof(val)); 132 return val; 133 } 134 double getDouble(pint_t addr) { 135 double val; 136 memcpy(&val, (void *)addr, sizeof(val)); 137 return val; 138 } 139 v128 getVector(pint_t addr) { 140 v128 val; 141 memcpy(&val, (void *)addr, sizeof(val)); 142 return val; 143 } 144 uintptr_t getP(pint_t addr); 145 static uint64_t getULEB128(pint_t &addr, pint_t end); 146 static int64_t getSLEB128(pint_t &addr, pint_t end); 147 148 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding); 149 bool findFunctionName(pint_t addr, char *buf, size_t bufLen, 150 unw_word_t *offset); 151 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); 152 bool findOtherFDE(pint_t targetAddr, pint_t &fde); 153 154 static LocalAddressSpace sThisAddressSpace; 155 }; 156 157 inline uintptr_t LocalAddressSpace::getP(pint_t addr) { 158 #if __LP64__ 159 return get64(addr); 160 #else 161 return get32(addr); 162 #endif 163 } 164 165 /// Read a ULEB128 into a 64-bit word. 166 inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) { 167 const uint8_t *p = (uint8_t *)addr; 168 const uint8_t *pend = (uint8_t *)end; 169 uint64_t result = 0; 170 int bit = 0; 171 do { 172 uint64_t b; 173 174 if (p == pend) 175 _LIBUNWIND_ABORT("truncated uleb128 expression"); 176 177 b = *p & 0x7f; 178 179 if (bit >= 64 || b << bit >> bit != b) { 180 _LIBUNWIND_ABORT("malformed uleb128 expression"); 181 } else { 182 result |= b << bit; 183 bit += 7; 184 } 185 } while (*p++ >= 0x80); 186 addr = (pint_t) p; 187 return result; 188 } 189 190 /// Read a SLEB128 into a 64-bit word. 191 inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { 192 const uint8_t *p = (uint8_t *)addr; 193 const uint8_t *pend = (uint8_t *)end; 194 int64_t result = 0; 195 int bit = 0; 196 uint8_t byte; 197 do { 198 if (p == pend) 199 _LIBUNWIND_ABORT("truncated sleb128 expression"); 200 byte = *p++; 201 result |= ((byte & 0x7f) << bit); 202 bit += 7; 203 } while (byte & 0x80); 204 // sign extend negative numbers 205 if ((byte & 0x40) != 0) 206 result |= (-1LL) << bit; 207 addr = (pint_t) p; 208 return result; 209 } 210 211 inline LocalAddressSpace::pint_t LocalAddressSpace::getEncodedP(pint_t &addr, 212 pint_t end, 213 uint8_t encoding) { 214 pint_t startAddr = addr; 215 const uint8_t *p = (uint8_t *)addr; 216 pint_t result; 217 218 // first get value 219 switch (encoding & 0x0F) { 220 case DW_EH_PE_ptr: 221 result = getP(addr); 222 p += sizeof(pint_t); 223 addr = (pint_t) p; 224 break; 225 case DW_EH_PE_uleb128: 226 result = (pint_t)getULEB128(addr, end); 227 break; 228 case DW_EH_PE_udata2: 229 result = get16(addr); 230 p += 2; 231 addr = (pint_t) p; 232 break; 233 case DW_EH_PE_udata4: 234 result = get32(addr); 235 p += 4; 236 addr = (pint_t) p; 237 break; 238 case DW_EH_PE_udata8: 239 result = (pint_t)get64(addr); 240 p += 8; 241 addr = (pint_t) p; 242 break; 243 case DW_EH_PE_sleb128: 244 result = (pint_t)getSLEB128(addr, end); 245 break; 246 case DW_EH_PE_sdata2: 247 // Sign extend from signed 16-bit value. 248 result = (pint_t)(int16_t)get16(addr); 249 p += 2; 250 addr = (pint_t) p; 251 break; 252 case DW_EH_PE_sdata4: 253 // Sign extend from signed 32-bit value. 254 result = (pint_t)(int32_t)get32(addr); 255 p += 4; 256 addr = (pint_t) p; 257 break; 258 case DW_EH_PE_sdata8: 259 result = (pint_t)get64(addr); 260 p += 8; 261 addr = (pint_t) p; 262 break; 263 default: 264 _LIBUNWIND_ABORT("unknown pointer encoding"); 265 } 266 267 // then add relative offset 268 switch (encoding & 0x70) { 269 case DW_EH_PE_absptr: 270 // do nothing 271 break; 272 case DW_EH_PE_pcrel: 273 result += startAddr; 274 break; 275 case DW_EH_PE_textrel: 276 _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported"); 277 break; 278 case DW_EH_PE_datarel: 279 _LIBUNWIND_ABORT("DW_EH_PE_datarel pointer encoding not supported"); 280 break; 281 case DW_EH_PE_funcrel: 282 _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported"); 283 break; 284 case DW_EH_PE_aligned: 285 _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported"); 286 break; 287 default: 288 _LIBUNWIND_ABORT("unknown pointer encoding"); 289 break; 290 } 291 292 if (encoding & DW_EH_PE_indirect) 293 result = getP(result); 294 295 return result; 296 } 297 298 #if __APPLE__ 299 struct dyld_unwind_sections 300 { 301 const struct mach_header* mh; 302 const void* dwarf_section; 303 uintptr_t dwarf_section_length; 304 const void* compact_unwind_section; 305 uintptr_t compact_unwind_section_length; 306 }; 307 #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \ 308 && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \ 309 || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 310 // In 10.7.0 or later, libSystem.dylib implements this function. 311 extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *); 312 #else 313 // In 10.6.x and earlier, we need to implement this functionality. 314 static inline bool _dyld_find_unwind_sections(void* addr, 315 dyld_unwind_sections* info) { 316 // Find mach-o image containing address. 317 Dl_info dlinfo; 318 if (!dladdr(addr, &dlinfo)) 319 return false; 320 const mach_header *mh = (const mach_header *)dlinfo.dli_saddr; 321 322 // Find dwarf unwind section in that image. 323 unsigned long size; 324 const uint8_t *p = getsectiondata(mh, "__TEXT", "__eh_frame", &size); 325 if (!p) 326 return false; 327 328 // Fill in return struct. 329 info->mh = mh; 330 info->dwarf_section = p; 331 info->dwarf_section_length = size; 332 info->compact_unwind_section = 0; 333 info->compact_unwind_section_length = 0; 334 335 return true; 336 } 337 #endif 338 #endif 339 340 inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, 341 UnwindInfoSections &info) { 342 #if __APPLE__ 343 dyld_unwind_sections dyldInfo; 344 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { 345 info.dso_base = (uintptr_t)dyldInfo.mh; 346 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND 347 info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section; 348 info.dwarf_section_length = dyldInfo.dwarf_section_length; 349 #endif 350 info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section; 351 info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length; 352 return true; 353 } 354 #elif LIBCXXABI_ARM_EHABI 355 #if !_LIBUNWIND_IS_BAREMETAL 356 int length = 0; 357 info.arm_section = (uintptr_t) dl_unwind_find_exidx( 358 (_Unwind_Ptr) targetAddr, &length); 359 info.arm_section_length = length; 360 #else 361 // Bare metal, statically linked 362 info.arm_section = (uintptr_t)(&__exidx_start); 363 info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start); 364 #endif 365 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x\n", 366 info.arm_section, info.arm_section_length); 367 if (info.arm_section && info.arm_section_length) 368 return true; 369 #endif 370 371 return false; 372 } 373 374 375 inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { 376 #if __APPLE__ 377 return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde)); 378 #else 379 // TO DO: if OS has way to dynamically register FDEs, check that. 380 return false; 381 #endif 382 } 383 384 inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, 385 size_t bufLen, 386 unw_word_t *offset) { 387 #if !_LIBUNWIND_IS_BAREMETAL 388 Dl_info dyldInfo; 389 if (dladdr((void *)addr, &dyldInfo)) { 390 if (dyldInfo.dli_sname != NULL) { 391 strlcpy(buf, dyldInfo.dli_sname, bufLen); 392 *offset = (addr - (pint_t) dyldInfo.dli_saddr); 393 return true; 394 } 395 } 396 #endif 397 return false; 398 } 399 400 401 402 #if UNW_REMOTE 403 404 /// OtherAddressSpace is used as a template parameter to UnwindCursor when 405 /// unwinding a thread in the another process. The other process can be a 406 /// different endianness and a different pointer size which is handled by 407 /// the P template parameter. 408 template <typename P> 409 class OtherAddressSpace { 410 public: 411 OtherAddressSpace(task_t task) : fTask(task) {} 412 413 typedef typename P::uint_t pint_t; 414 415 uint8_t get8(pint_t addr); 416 uint16_t get16(pint_t addr); 417 uint32_t get32(pint_t addr); 418 uint64_t get64(pint_t addr); 419 pint_t getP(pint_t addr); 420 uint64_t getULEB128(pint_t &addr, pint_t end); 421 int64_t getSLEB128(pint_t &addr, pint_t end); 422 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding); 423 bool findFunctionName(pint_t addr, char *buf, size_t bufLen, 424 unw_word_t *offset); 425 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); 426 bool findOtherFDE(pint_t targetAddr, pint_t &fde); 427 private: 428 void *localCopy(pint_t addr); 429 430 task_t fTask; 431 }; 432 433 template <typename P> uint8_t OtherAddressSpace<P>::get8(pint_t addr) { 434 return *((uint8_t *)localCopy(addr)); 435 } 436 437 template <typename P> uint16_t OtherAddressSpace<P>::get16(pint_t addr) { 438 return P::E::get16(*(uint16_t *)localCopy(addr)); 439 } 440 441 template <typename P> uint32_t OtherAddressSpace<P>::get32(pint_t addr) { 442 return P::E::get32(*(uint32_t *)localCopy(addr)); 443 } 444 445 template <typename P> uint64_t OtherAddressSpace<P>::get64(pint_t addr) { 446 return P::E::get64(*(uint64_t *)localCopy(addr)); 447 } 448 449 template <typename P> 450 typename P::uint_t OtherAddressSpace<P>::getP(pint_t addr) { 451 return P::getP(*(uint64_t *)localCopy(addr)); 452 } 453 454 template <typename P> 455 uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) { 456 uintptr_t size = (end - addr); 457 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); 458 LocalAddressSpace::pint_t sladdr = laddr; 459 uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size); 460 addr += (laddr - sladdr); 461 return result; 462 } 463 464 template <typename P> 465 int64_t OtherAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) { 466 uintptr_t size = (end - addr); 467 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); 468 LocalAddressSpace::pint_t sladdr = laddr; 469 uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size); 470 addr += (laddr - sladdr); 471 return result; 472 } 473 474 template <typename P> void *OtherAddressSpace<P>::localCopy(pint_t addr) { 475 // FIX ME 476 } 477 478 template <typename P> 479 bool OtherAddressSpace<P>::findFunctionName(pint_t addr, char *buf, 480 size_t bufLen, unw_word_t *offset) { 481 // FIX ME 482 } 483 484 /// unw_addr_space is the base class that abstract unw_addr_space_t type in 485 /// libunwind.h points to. 486 struct unw_addr_space { 487 cpu_type_t cpuType; 488 task_t taskPort; 489 }; 490 491 /// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points 492 /// to when examining 493 /// a 32-bit intel process. 494 struct unw_addr_space_i386 : public unw_addr_space { 495 unw_addr_space_i386(task_t task) : oas(task) {} 496 OtherAddressSpace<Pointer32<LittleEndian> > oas; 497 }; 498 499 /// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t 500 /// points to when examining 501 /// a 64-bit intel process. 502 struct unw_addr_space_x86_64 : public unw_addr_space { 503 unw_addr_space_x86_64(task_t task) : oas(task) {} 504 OtherAddressSpace<Pointer64<LittleEndian> > oas; 505 }; 506 507 /// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points 508 /// to when examining 509 /// a 32-bit PowerPC process. 510 struct unw_addr_space_ppc : public unw_addr_space { 511 unw_addr_space_ppc(task_t task) : oas(task) {} 512 OtherAddressSpace<Pointer32<BigEndian> > oas; 513 }; 514 515 #endif // UNW_REMOTE 516 517 } // namespace libunwind 518 519 #endif // __ADDRESSSPACE_HPP__ 520