1 //===------------------------- AddressSpace.hpp ---------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 // 8 // Abstracts accessing local vs remote address spaces. 9 // 10 //===----------------------------------------------------------------------===// 11 12 #ifndef __ADDRESSSPACE_HPP__ 13 #define __ADDRESSSPACE_HPP__ 14 15 #include <stdint.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <sys/tree.h> 20 21 #include "libunwind.h" 22 #include "config.h" 23 #include "dwarf2.h" 24 #include "EHHeaderParser.hpp" 25 #include "Registers.hpp" 26 27 #ifndef _LIBUNWIND_USE_DLADDR 28 #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) 29 #define _LIBUNWIND_USE_DLADDR 1 30 #else 31 #define _LIBUNWIND_USE_DLADDR 0 32 #endif 33 #endif 34 35 #if _LIBUNWIND_USE_DLADDR 36 #include <dlfcn.h> 37 #if defined(__ELF__) && defined(_LIBUNWIND_LINK_DL_LIB) 38 #pragma comment(lib, "dl") 39 #endif 40 #endif 41 42 #if defined(_LIBUNWIND_ARM_EHABI) 43 struct EHABIIndexEntry { 44 uint32_t functionOffset; 45 uint32_t data; 46 }; 47 #endif 48 49 #ifdef __APPLE__ 50 51 struct dyld_unwind_sections 52 { 53 const struct mach_header* mh; 54 const void* dwarf_section; 55 uintptr_t dwarf_section_length; 56 const void* compact_unwind_section; 57 uintptr_t compact_unwind_section_length; 58 }; 59 60 // In 10.7.0 or later, libSystem.dylib implements this function. 61 extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *); 62 63 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) 64 65 // When statically linked on bare-metal, the symbols for the EH table are looked 66 // up without going through the dynamic loader. 67 68 // The following linker script may be used to produce the necessary sections and symbols. 69 // Unless the --eh-frame-hdr linker option is provided, the section is not generated 70 // and does not take space in the output file. 71 // 72 // .eh_frame : 73 // { 74 // __eh_frame_start = .; 75 // KEEP(*(.eh_frame)) 76 // __eh_frame_end = .; 77 // } 78 // 79 // .eh_frame_hdr : 80 // { 81 // KEEP(*(.eh_frame_hdr)) 82 // } 83 // 84 // __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; 85 // __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; 86 87 extern char __eh_frame_start; 88 extern char __eh_frame_end; 89 90 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) 91 extern char __eh_frame_hdr_start; 92 extern char __eh_frame_hdr_end; 93 #endif 94 95 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) 96 97 // When statically linked on bare-metal, the symbols for the EH table are looked 98 // up without going through the dynamic loader. 99 extern char __exidx_start; 100 extern char __exidx_end; 101 102 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) 103 104 #include <windows.h> 105 #include <psapi.h> 106 107 #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) || \ 108 defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX) 109 110 #include <link.h> 111 112 #endif 113 114 namespace libunwind { 115 116 /// Used by findUnwindSections() to return info about needed sections. 117 struct UnwindInfoSections { 118 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || \ 119 defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) || \ 120 defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) 121 // No dso_base for SEH. 122 uintptr_t dso_base; 123 #endif 124 #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) 125 uintptr_t text_segment_length; 126 #endif 127 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 128 uintptr_t dwarf_section; 129 uintptr_t dwarf_section_length; 130 #endif 131 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) 132 uintptr_t dwarf_index_section; 133 uintptr_t dwarf_index_section_length; 134 #endif 135 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) 136 uintptr_t compact_unwind_section; 137 uintptr_t compact_unwind_section_length; 138 #endif 139 #if defined(_LIBUNWIND_ARM_EHABI) 140 uintptr_t arm_section; 141 uintptr_t arm_section_length; 142 #endif 143 }; 144 145 class UnwindInfoSectionsCache { 146 public: 147 148 struct CacheItem { 149 CacheItem(UnwindInfoSections &uis, uintptr_t pc) 150 : m_uis(uis), m_pc(pc) { 151 } 152 CacheItem(uintptr_t pc) 153 : m_pc(pc) { 154 } 155 156 UnwindInfoSections m_uis; 157 uintptr_t m_pc; 158 159 RB_ENTRY(CacheItem) entry; 160 }; 161 162 typedef uintptr_t CacheItemKey; 163 164 int CacheCmp(struct CacheItem *c1, struct CacheItem *c2) { 165 return (c1->m_pc < c2->m_pc ? -1 : c1->m_pc > c2->m_pc); 166 } 167 168 UnwindInfoSectionsCache() { 169 m_head = RB_INITIALIZER(&head); 170 } 171 172 bool getUnwindInfoSectionsForPC(CacheItemKey key, UnwindInfoSections &uis) { 173 UnwindInfoSections *result = nullptr; 174 if (m_prev_req_item && m_prev_req_item->m_pc == key) 175 result = &m_prev_req_item->m_uis; 176 else { 177 struct CacheItem find(key), *res; 178 res = RB_FIND(CacheTree, &m_head, &find); 179 if (res) { 180 m_prev_req_item = res; 181 result = &res->m_uis; 182 } 183 } 184 if (result) { 185 uis = *result; 186 return true; 187 } 188 return false; 189 } 190 191 void setUnwindInfoSectionsForPC(CacheItemKey key, UnwindInfoSections &uis) { 192 CacheItem *p_item(new CacheItem(uis, key)); 193 RB_INSERT(CacheTree, &m_head, p_item); 194 } 195 196 private: 197 CacheItem *m_prev_req_item = nullptr; 198 RB_HEAD(CacheTree, CacheItem) m_head; 199 RB_GENERATE(CacheTree, CacheItem, entry, CacheCmp); 200 }; 201 202 /// LocalAddressSpace is used as a template parameter to UnwindCursor when 203 /// unwinding a thread in the same process. The wrappers compile away, 204 /// making local unwinds fast. 205 class _LIBUNWIND_HIDDEN LocalAddressSpace { 206 public: 207 typedef uintptr_t pint_t; 208 typedef intptr_t sint_t; 209 uint8_t get8(pint_t addr) { 210 uint8_t val; 211 memcpy(&val, (void *)addr, sizeof(val)); 212 return val; 213 } 214 uint16_t get16(pint_t addr) { 215 uint16_t val; 216 memcpy(&val, (void *)addr, sizeof(val)); 217 return val; 218 } 219 uint32_t get32(pint_t addr) { 220 uint32_t val; 221 memcpy(&val, (void *)addr, sizeof(val)); 222 return val; 223 } 224 uint64_t get64(pint_t addr) { 225 uint64_t val; 226 memcpy(&val, (void *)addr, sizeof(val)); 227 return val; 228 } 229 double getDouble(pint_t addr) { 230 double val; 231 memcpy(&val, (void *)addr, sizeof(val)); 232 return val; 233 } 234 v128 getVector(pint_t addr) { 235 v128 val; 236 memcpy(&val, (void *)addr, sizeof(val)); 237 return val; 238 } 239 uintptr_t getP(pint_t addr); 240 uint64_t getRegister(pint_t addr); 241 static uint64_t getULEB128(pint_t &addr, pint_t end); 242 static int64_t getSLEB128(pint_t &addr, pint_t end); 243 244 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, 245 pint_t datarelBase = 0); 246 bool findFunctionName(pint_t addr, char *buf, size_t bufLen, 247 unw_word_t *offset); 248 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); 249 bool findOtherFDE(pint_t targetAddr, pint_t &fde); 250 251 static LocalAddressSpace sThisAddressSpace; 252 }; 253 254 inline uintptr_t LocalAddressSpace::getP(pint_t addr) { 255 #if __SIZEOF_POINTER__ == 8 256 return get64(addr); 257 #else 258 return get32(addr); 259 #endif 260 } 261 262 inline uint64_t LocalAddressSpace::getRegister(pint_t addr) { 263 #if __SIZEOF_POINTER__ == 8 || defined(__mips64) 264 return get64(addr); 265 #else 266 return get32(addr); 267 #endif 268 } 269 270 /// Read a ULEB128 into a 64-bit word. 271 inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) { 272 const uint8_t *p = (uint8_t *)addr; 273 const uint8_t *pend = (uint8_t *)end; 274 uint64_t result = 0; 275 int bit = 0; 276 do { 277 uint64_t b; 278 279 if (p == pend) 280 _LIBUNWIND_ABORT("truncated uleb128 expression"); 281 282 b = *p & 0x7f; 283 284 if (bit >= 64 || b << bit >> bit != b) { 285 _LIBUNWIND_ABORT("malformed uleb128 expression"); 286 } else { 287 result |= b << bit; 288 bit += 7; 289 } 290 } while (*p++ >= 0x80); 291 addr = (pint_t) p; 292 return result; 293 } 294 295 /// Read a SLEB128 into a 64-bit word. 296 inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { 297 const uint8_t *p = (uint8_t *)addr; 298 const uint8_t *pend = (uint8_t *)end; 299 int64_t result = 0; 300 int bit = 0; 301 uint8_t byte; 302 do { 303 if (p == pend) 304 _LIBUNWIND_ABORT("truncated sleb128 expression"); 305 byte = *p++; 306 result |= (uint64_t)(byte & 0x7f) << bit; 307 bit += 7; 308 } while (byte & 0x80); 309 // sign extend negative numbers 310 if ((byte & 0x40) != 0 && bit < 64) 311 result |= (-1ULL) << bit; 312 addr = (pint_t) p; 313 return result; 314 } 315 316 inline LocalAddressSpace::pint_t 317 LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, 318 pint_t datarelBase) { 319 pint_t startAddr = addr; 320 const uint8_t *p = (uint8_t *)addr; 321 pint_t result; 322 323 if (encoding == DW_EH_PE_omit) { 324 return (pint_t)NULL; 325 } 326 327 // first get value 328 switch (encoding & 0x0F) { 329 case DW_EH_PE_ptr: 330 result = getP(addr); 331 p += sizeof(pint_t); 332 addr = (pint_t) p; 333 break; 334 case DW_EH_PE_uleb128: 335 result = (pint_t)getULEB128(addr, end); 336 break; 337 case DW_EH_PE_udata2: 338 result = get16(addr); 339 p += 2; 340 addr = (pint_t) p; 341 break; 342 case DW_EH_PE_udata4: 343 result = get32(addr); 344 p += 4; 345 addr = (pint_t) p; 346 break; 347 case DW_EH_PE_udata8: 348 result = (pint_t)get64(addr); 349 p += 8; 350 addr = (pint_t) p; 351 break; 352 case DW_EH_PE_sleb128: 353 result = (pint_t)getSLEB128(addr, end); 354 break; 355 case DW_EH_PE_sdata2: 356 // Sign extend from signed 16-bit value. 357 result = (pint_t)(int16_t)get16(addr); 358 p += 2; 359 addr = (pint_t) p; 360 break; 361 case DW_EH_PE_sdata4: 362 // Sign extend from signed 32-bit value. 363 result = (pint_t)(int32_t)get32(addr); 364 p += 4; 365 addr = (pint_t) p; 366 break; 367 case DW_EH_PE_sdata8: 368 result = (pint_t)get64(addr); 369 p += 8; 370 addr = (pint_t) p; 371 break; 372 default: 373 _LIBUNWIND_ABORT("unknown pointer encoding"); 374 } 375 376 // then add relative offset 377 switch (encoding & 0x70) { 378 case DW_EH_PE_absptr: 379 // do nothing 380 break; 381 case DW_EH_PE_pcrel: 382 result += startAddr; 383 break; 384 case DW_EH_PE_textrel: 385 _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported"); 386 break; 387 case DW_EH_PE_datarel: 388 // DW_EH_PE_datarel is only valid in a few places, so the parameter has a 389 // default value of 0, and we abort in the event that someone calls this 390 // function with a datarelBase of 0 and DW_EH_PE_datarel encoding. 391 if (datarelBase == 0) 392 _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0"); 393 result += datarelBase; 394 break; 395 case DW_EH_PE_funcrel: 396 _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported"); 397 break; 398 case DW_EH_PE_aligned: 399 _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported"); 400 break; 401 default: 402 _LIBUNWIND_ABORT("unknown pointer encoding"); 403 break; 404 } 405 406 if (encoding & DW_EH_PE_indirect) 407 result = getP(result); 408 409 return result; 410 } 411 412 #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) 413 414 // The ElfW() macro for pointer-size independent ELF header traversal is not 415 // provided by <link.h> on some systems (e.g., FreeBSD). On these systems the 416 // data structures are just called Elf_XXX. Define ElfW() locally. 417 #if !defined(ElfW) 418 #define ElfW(type) Elf_##type 419 #endif 420 #if !defined(Elf_Half) 421 typedef ElfW(Half) Elf_Half; 422 #endif 423 #if !defined(Elf_Phdr) 424 typedef ElfW(Phdr) Elf_Phdr; 425 #endif 426 #if !defined(Elf_Addr) 427 typedef ElfW(Addr) Elf_Addr; 428 #endif 429 430 static Elf_Addr calculateImageBase(struct dl_phdr_info *pinfo) { 431 Elf_Addr image_base = pinfo->dlpi_addr; 432 #if defined(__ANDROID__) && __ANDROID_API__ < 18 433 if (image_base == 0) { 434 // Normally, an image base of 0 indicates a non-PIE executable. On 435 // versions of Android prior to API 18, the dynamic linker reported a 436 // dlpi_addr of 0 for PIE executables. Compute the true image base 437 // using the PT_PHDR segment. 438 // See https://github.com/android/ndk/issues/505. 439 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { 440 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; 441 if (phdr->p_type == PT_PHDR) { 442 image_base = reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) - 443 phdr->p_vaddr; 444 break; 445 } 446 } 447 } 448 #endif 449 return image_base; 450 } 451 452 struct _LIBUNWIND_HIDDEN dl_iterate_cb_data { 453 LocalAddressSpace *addressSpace; 454 UnwindInfoSections *sects; 455 uintptr_t targetAddr; 456 }; 457 458 #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) 459 #include "FrameHeaderCache.hpp" 460 461 // Typically there is one cache per process, but when libunwind is built as a 462 // hermetic static library, then each shared object may have its own cache. 463 static FrameHeaderCache TheFrameHeaderCache; 464 #endif 465 466 static bool checkAddrInSegment(const Elf_Phdr *phdr, size_t image_base, 467 dl_iterate_cb_data *cbdata) { 468 if (phdr->p_type == PT_LOAD) { 469 uintptr_t begin = image_base + phdr->p_vaddr; 470 uintptr_t end = begin + phdr->p_memsz; 471 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { 472 cbdata->sects->dso_base = begin; 473 cbdata->sects->text_segment_length = phdr->p_memsz; 474 return true; 475 } 476 } 477 return false; 478 } 479 480 static bool checkForUnwindInfoSegment(const Elf_Phdr *phdr, size_t image_base, 481 dl_iterate_cb_data *cbdata) { 482 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) 483 if (phdr->p_type == PT_GNU_EH_FRAME) { 484 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; 485 uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr; 486 cbdata->sects->dwarf_index_section = eh_frame_hdr_start; 487 cbdata->sects->dwarf_index_section_length = phdr->p_memsz; 488 if (EHHeaderParser<LocalAddressSpace>::decodeEHHdr( 489 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, 490 hdrInfo)) { 491 // .eh_frame_hdr records the start of .eh_frame, but not its size. 492 // Rely on a zero terminator to find the end of the section. 493 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; 494 cbdata->sects->dwarf_section_length = UINTPTR_MAX; 495 return true; 496 } 497 } 498 return false; 499 #elif defined(_LIBUNWIND_ARM_EHABI) 500 if (phdr->p_type == PT_ARM_EXIDX) { 501 uintptr_t exidx_start = image_base + phdr->p_vaddr; 502 cbdata->sects->arm_section = exidx_start; 503 cbdata->sects->arm_section_length = phdr->p_memsz; 504 return true; 505 } 506 return false; 507 #else 508 #error Need one of _LIBUNWIND_SUPPORT_DWARF_INDEX or _LIBUNWIND_ARM_EHABI 509 #endif 510 } 511 512 static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, 513 size_t pinfo_size, void *data) { 514 auto cbdata = static_cast<dl_iterate_cb_data *>(data); 515 if (pinfo->dlpi_phnum == 0 || cbdata->targetAddr < pinfo->dlpi_addr) 516 return 0; 517 #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) 518 if (TheFrameHeaderCache.find(pinfo, pinfo_size, data)) 519 return 1; 520 #else 521 // Avoid warning about unused variable. 522 (void)pinfo_size; 523 #endif 524 525 Elf_Addr image_base = calculateImageBase(pinfo); 526 527 // Most shared objects seen in this callback function likely don't contain the 528 // target address, so optimize for that. Scan for a matching PT_LOAD segment 529 // first and bail when it isn't found. 530 bool found_text = false; 531 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; ++i) { 532 if (checkAddrInSegment(&pinfo->dlpi_phdr[i], image_base, cbdata)) { 533 found_text = true; 534 break; 535 } 536 } 537 if (!found_text) 538 return 0; 539 540 // PT_GNU_EH_FRAME and PT_ARM_EXIDX are usually near the end. Iterate 541 // backward. 542 bool found_unwind = false; 543 for (Elf_Half i = pinfo->dlpi_phnum; i > 0; i--) { 544 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i - 1]; 545 if (checkForUnwindInfoSegment(phdr, image_base, cbdata)) { 546 found_unwind = true; 547 break; 548 } 549 } 550 if (!found_unwind) 551 return 0; 552 553 #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) 554 TheFrameHeaderCache.add(cbdata->sects); 555 #endif 556 return 1; 557 } 558 559 #endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) 560 561 562 inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, 563 UnwindInfoSections &info) { 564 #ifdef __APPLE__ 565 dyld_unwind_sections dyldInfo; 566 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { 567 info.dso_base = (uintptr_t)dyldInfo.mh; 568 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 569 info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section; 570 info.dwarf_section_length = dyldInfo.dwarf_section_length; 571 #endif 572 info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section; 573 info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length; 574 return true; 575 } 576 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) 577 info.dso_base = 0; 578 // Bare metal is statically linked, so no need to ask the dynamic loader 579 info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start); 580 info.dwarf_section = (uintptr_t)(&__eh_frame_start); 581 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", 582 (void *)info.dwarf_section, (void *)info.dwarf_section_length); 583 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) 584 info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start); 585 info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start); 586 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p", 587 (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length); 588 #endif 589 if (info.dwarf_section_length) 590 return true; 591 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) 592 // Bare metal is statically linked, so no need to ask the dynamic loader 593 info.arm_section = (uintptr_t)(&__exidx_start); 594 info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start); 595 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", 596 (void *)info.arm_section, (void *)info.arm_section_length); 597 if (info.arm_section && info.arm_section_length) 598 return true; 599 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) 600 HMODULE mods[1024]; 601 HANDLE process = GetCurrentProcess(); 602 DWORD needed; 603 604 if (!EnumProcessModules(process, mods, sizeof(mods), &needed)) { 605 DWORD err = GetLastError(); 606 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: EnumProcessModules failed, " 607 "returned error %d", (int)err); 608 return false; 609 } 610 611 for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) { 612 PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i]; 613 PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew); 614 PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader; 615 PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh); 616 bool found_obj = false; 617 bool found_hdr = false; 618 619 info.dso_base = (uintptr_t)mods[i]; 620 for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) { 621 uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i]; 622 uintptr_t end = begin + pish->Misc.VirtualSize; 623 if (!strncmp((const char *)pish->Name, ".text", 624 IMAGE_SIZEOF_SHORT_NAME)) { 625 if (targetAddr >= begin && targetAddr < end) 626 found_obj = true; 627 } else if (!strncmp((const char *)pish->Name, ".eh_frame", 628 IMAGE_SIZEOF_SHORT_NAME)) { 629 info.dwarf_section = begin; 630 info.dwarf_section_length = pish->Misc.VirtualSize; 631 found_hdr = true; 632 } 633 if (found_obj && found_hdr) 634 return true; 635 } 636 } 637 return false; 638 #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) 639 // Don't even bother, since Windows has functions that do all this stuff 640 // for us. 641 (void)targetAddr; 642 (void)info; 643 return true; 644 #elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX) 645 int length = 0; 646 info.arm_section = 647 (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); 648 info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry); 649 if (info.arm_section && info.arm_section_length) 650 return true; 651 #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) 652 dl_iterate_cb_data cb_data = {this, &info, targetAddr}; 653 int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); 654 return static_cast<bool>(found); 655 #endif 656 657 return false; 658 } 659 660 661 inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { 662 // TO DO: if OS has way to dynamically register FDEs, check that. 663 (void)targetAddr; 664 (void)fde; 665 return false; 666 } 667 668 inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, 669 size_t bufLen, 670 unw_word_t *offset) { 671 #if _LIBUNWIND_USE_DLADDR 672 Dl_info dyldInfo; 673 if (dladdr((void *)addr, &dyldInfo)) { 674 if (dyldInfo.dli_sname != NULL) { 675 snprintf(buf, bufLen, "%s", dyldInfo.dli_sname); 676 *offset = (addr - (pint_t) dyldInfo.dli_saddr); 677 return true; 678 } 679 } 680 #else 681 (void)addr; 682 (void)buf; 683 (void)bufLen; 684 (void)offset; 685 #endif 686 return false; 687 } 688 689 } // namespace libunwind 690 691 #endif // __ADDRESSSPACE_HPP__ 692