1 //===------------------------- AddressSpace.hpp ---------------------------===//
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
8 // Abstracts accessing local vs remote address spaces.
10 //===----------------------------------------------------------------------===//
12 #ifndef __ADDRESSSPACE_HPP__
13 #define __ADDRESSSPACE_HPP__
20 #ifndef _LIBUNWIND_USE_DLADDR
21 #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
22 #define _LIBUNWIND_USE_DLADDR 1
24 #define _LIBUNWIND_USE_DLADDR 0
28 #if _LIBUNWIND_USE_DLADDR
30 #if defined(__ELF__) && defined(_LIBUNWIND_LINK_DL_LIB)
31 #pragma comment(lib, "dl")
35 #if defined(_LIBUNWIND_ARM_EHABI)
36 struct EHABIIndexEntry {
37 uint32_t functionOffset;
43 #include <mach-o/getsect.h>
45 bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde);
49 #include "libunwind.h"
52 #include "EHHeaderParser.hpp"
53 #include "Registers.hpp"
57 struct dyld_unwind_sections
59 const struct mach_header* mh;
60 const void* dwarf_section;
61 uintptr_t dwarf_section_length;
62 const void* compact_unwind_section;
63 uintptr_t compact_unwind_section_length;
65 #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
66 && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \
67 || defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
68 // In 10.7.0 or later, libSystem.dylib implements this function.
69 extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
71 // In 10.6.x and earlier, we need to implement this functionality. Note
72 // that this requires a newer version of libmacho (from cctools) than is
73 // present in libSystem on 10.6.x (for getsectiondata).
74 static inline bool _dyld_find_unwind_sections(void* addr,
75 dyld_unwind_sections* info) {
76 // Find mach-o image containing address.
78 if (!dladdr(addr, &dlinfo))
81 const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase;
83 const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase;
86 // Initialize the return struct
87 info->mh = (const struct mach_header *)mh;
88 info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length);
89 info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length);
91 if (!info->dwarf_section) {
92 info->dwarf_section_length = 0;
95 if (!info->compact_unwind_section) {
96 info->compact_unwind_section_length = 0;
103 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
105 // When statically linked on bare-metal, the symbols for the EH table are looked
106 // up without going through the dynamic loader.
108 // The following linker script may be used to produce the necessary sections and symbols.
109 // Unless the --eh-frame-hdr linker option is provided, the section is not generated
110 // and does not take space in the output file.
114 // __eh_frame_start = .;
115 // KEEP(*(.eh_frame))
116 // __eh_frame_end = .;
121 // KEEP(*(.eh_frame_hdr))
124 // __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
125 // __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
127 extern char __eh_frame_start;
128 extern char __eh_frame_end;
130 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
131 extern char __eh_frame_hdr_start;
132 extern char __eh_frame_hdr_end;
135 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
137 // When statically linked on bare-metal, the symbols for the EH table are looked
138 // up without going through the dynamic loader.
139 extern char __exidx_start;
140 extern char __exidx_end;
142 #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
144 // ELF-based systems may use dl_iterate_phdr() to access sections
145 // containing unwinding information. The ElfW() macro for pointer-size
146 // independent ELF header traversal is not provided by <link.h> on some
147 // systems (e.g., FreeBSD). On these systems the data structures are
148 // just called Elf_XXX. Define ElfW() locally.
156 #define ElfW(type) Elf_##type
161 namespace libunwind {
163 /// Used by findUnwindSections() to return info about needed sections.
164 struct UnwindInfoSections {
165 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \
166 defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
167 // No dso_base for SEH or ARM EHABI.
170 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
171 uintptr_t dwarf_section;
172 uintptr_t dwarf_section_length;
174 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
175 uintptr_t dwarf_index_section;
176 uintptr_t dwarf_index_section_length;
178 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
179 uintptr_t compact_unwind_section;
180 uintptr_t compact_unwind_section_length;
182 #if defined(_LIBUNWIND_ARM_EHABI)
183 uintptr_t arm_section;
184 uintptr_t arm_section_length;
189 /// LocalAddressSpace is used as a template parameter to UnwindCursor when
190 /// unwinding a thread in the same process. The wrappers compile away,
191 /// making local unwinds fast.
192 class _LIBUNWIND_HIDDEN LocalAddressSpace {
194 typedef uintptr_t pint_t;
195 typedef intptr_t sint_t;
196 uint8_t get8(pint_t addr) {
198 memcpy(&val, (void *)addr, sizeof(val));
201 uint16_t get16(pint_t addr) {
203 memcpy(&val, (void *)addr, sizeof(val));
206 uint32_t get32(pint_t addr) {
208 memcpy(&val, (void *)addr, sizeof(val));
211 uint64_t get64(pint_t addr) {
213 memcpy(&val, (void *)addr, sizeof(val));
216 double getDouble(pint_t addr) {
218 memcpy(&val, (void *)addr, sizeof(val));
221 v128 getVector(pint_t addr) {
223 memcpy(&val, (void *)addr, sizeof(val));
226 uintptr_t getP(pint_t addr);
227 uint64_t getRegister(pint_t addr);
228 static uint64_t getULEB128(pint_t &addr, pint_t end);
229 static int64_t getSLEB128(pint_t &addr, pint_t end);
231 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
232 pint_t datarelBase = 0);
233 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
235 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
236 bool findOtherFDE(pint_t targetAddr, pint_t &fde);
238 static LocalAddressSpace sThisAddressSpace;
241 inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
242 #if __SIZEOF_POINTER__ == 8
249 inline uint64_t LocalAddressSpace::getRegister(pint_t addr) {
250 #if __SIZEOF_POINTER__ == 8 || defined(__mips64)
257 /// Read a ULEB128 into a 64-bit word.
258 inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
259 const uint8_t *p = (uint8_t *)addr;
260 const uint8_t *pend = (uint8_t *)end;
267 _LIBUNWIND_ABORT("truncated uleb128 expression");
271 if (bit >= 64 || b << bit >> bit != b) {
272 _LIBUNWIND_ABORT("malformed uleb128 expression");
277 } while (*p++ >= 0x80);
282 /// Read a SLEB128 into a 64-bit word.
283 inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
284 const uint8_t *p = (uint8_t *)addr;
285 const uint8_t *pend = (uint8_t *)end;
291 _LIBUNWIND_ABORT("truncated sleb128 expression");
293 result |= ((byte & 0x7f) << bit);
295 } while (byte & 0x80);
296 // sign extend negative numbers
297 if ((byte & 0x40) != 0)
298 result |= (-1ULL) << bit;
303 inline LocalAddressSpace::pint_t
304 LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
305 pint_t datarelBase) {
306 pint_t startAddr = addr;
307 const uint8_t *p = (uint8_t *)addr;
311 switch (encoding & 0x0F) {
317 case DW_EH_PE_uleb128:
318 result = (pint_t)getULEB128(addr, end);
320 case DW_EH_PE_udata2:
321 result = get16(addr);
325 case DW_EH_PE_udata4:
326 result = get32(addr);
330 case DW_EH_PE_udata8:
331 result = (pint_t)get64(addr);
335 case DW_EH_PE_sleb128:
336 result = (pint_t)getSLEB128(addr, end);
338 case DW_EH_PE_sdata2:
339 // Sign extend from signed 16-bit value.
340 result = (pint_t)(int16_t)get16(addr);
344 case DW_EH_PE_sdata4:
345 // Sign extend from signed 32-bit value.
346 result = (pint_t)(int32_t)get32(addr);
350 case DW_EH_PE_sdata8:
351 result = (pint_t)get64(addr);
356 _LIBUNWIND_ABORT("unknown pointer encoding");
359 // then add relative offset
360 switch (encoding & 0x70) {
361 case DW_EH_PE_absptr:
367 case DW_EH_PE_textrel:
368 _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported");
370 case DW_EH_PE_datarel:
371 // DW_EH_PE_datarel is only valid in a few places, so the parameter has a
372 // default value of 0, and we abort in the event that someone calls this
373 // function with a datarelBase of 0 and DW_EH_PE_datarel encoding.
374 if (datarelBase == 0)
375 _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0");
376 result += datarelBase;
378 case DW_EH_PE_funcrel:
379 _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported");
381 case DW_EH_PE_aligned:
382 _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported");
385 _LIBUNWIND_ABORT("unknown pointer encoding");
389 if (encoding & DW_EH_PE_indirect)
390 result = getP(result);
395 inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
396 UnwindInfoSections &info) {
398 dyld_unwind_sections dyldInfo;
399 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
400 info.dso_base = (uintptr_t)dyldInfo.mh;
401 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
402 info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section;
403 info.dwarf_section_length = dyldInfo.dwarf_section_length;
405 info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section;
406 info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
409 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
410 // Bare metal is statically linked, so no need to ask the dynamic loader
411 info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start);
412 info.dwarf_section = (uintptr_t)(&__eh_frame_start);
413 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
414 (void *)info.dwarf_section, (void *)info.dwarf_section_length);
415 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
416 info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start);
417 info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start);
418 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p",
419 (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length);
421 if (info.dwarf_section_length)
423 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
424 // Bare metal is statically linked, so no need to ask the dynamic loader
425 info.arm_section = (uintptr_t)(&__exidx_start);
426 info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start);
427 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
428 (void *)info.arm_section, (void *)info.arm_section_length);
429 if (info.arm_section && info.arm_section_length)
431 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
433 HANDLE process = GetCurrentProcess();
436 if (!EnumProcessModules(process, mods, sizeof(mods), &needed)) {
437 DWORD err = GetLastError();
438 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: EnumProcessModules failed, "
439 "returned error %d", (int)err);
443 for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) {
444 PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i];
445 PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew);
446 PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
447 PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh);
448 bool found_obj = false;
449 bool found_hdr = false;
451 info.dso_base = (uintptr_t)mods[i];
452 for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) {
453 uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i];
454 uintptr_t end = begin + pish->Misc.VirtualSize;
455 if (!strncmp((const char *)pish->Name, ".text",
456 IMAGE_SIZEOF_SHORT_NAME)) {
457 if (targetAddr >= begin && targetAddr < end)
459 } else if (!strncmp((const char *)pish->Name, ".eh_frame",
460 IMAGE_SIZEOF_SHORT_NAME)) {
461 info.dwarf_section = begin;
462 info.dwarf_section_length = pish->Misc.VirtualSize;
465 if (found_obj && found_hdr)
470 #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
471 // Don't even bother, since Windows has functions that do all this stuff
476 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__)
477 // For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After
478 // API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster.
481 (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length);
482 info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry);
483 if (info.arm_section && info.arm_section_length)
485 #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
486 struct dl_iterate_cb_data {
487 LocalAddressSpace *addressSpace;
488 UnwindInfoSections *sects;
489 uintptr_t targetAddr;
492 dl_iterate_cb_data cb_data = {this, &info, targetAddr};
493 int found = dl_iterate_phdr(
494 [](struct dl_phdr_info *pinfo, size_t, void *data) -> int {
495 auto cbdata = static_cast<dl_iterate_cb_data *>(data);
496 bool found_obj = false;
497 bool found_hdr = false;
500 assert(cbdata->sects);
502 if (cbdata->targetAddr < pinfo->dlpi_addr) {
506 #if !defined(Elf_Half)
507 typedef ElfW(Half) Elf_Half;
509 #if !defined(Elf_Phdr)
510 typedef ElfW(Phdr) Elf_Phdr;
512 #if !defined(Elf_Addr)
513 typedef ElfW(Addr) Elf_Addr;
516 Elf_Addr image_base = pinfo->dlpi_addr;
518 #if defined(__ANDROID__) && __ANDROID_API__ < 18
519 if (image_base == 0) {
520 // Normally, an image base of 0 indicates a non-PIE executable. On
521 // versions of Android prior to API 18, the dynamic linker reported a
522 // dlpi_addr of 0 for PIE executables. Compute the true image base
523 // using the PT_PHDR segment.
524 // See https://github.com/android/ndk/issues/505.
525 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
526 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
527 if (phdr->p_type == PT_PHDR) {
528 image_base = reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) -
536 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
537 #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
538 #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
540 size_t object_length;
542 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
543 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
544 if (phdr->p_type == PT_LOAD) {
545 uintptr_t begin = image_base + phdr->p_vaddr;
546 uintptr_t end = begin + phdr->p_memsz;
547 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) {
548 cbdata->sects->dso_base = begin;
549 object_length = phdr->p_memsz;
552 } else if (phdr->p_type == PT_GNU_EH_FRAME) {
553 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
554 uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr;
555 cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
556 cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
557 found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
558 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
561 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
565 if (found_obj && found_hdr) {
566 cbdata->sects->dwarf_section_length = object_length;
571 #else // defined(_LIBUNWIND_ARM_EHABI)
572 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
573 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
574 if (phdr->p_type == PT_LOAD) {
575 uintptr_t begin = image_base + phdr->p_vaddr;
576 uintptr_t end = begin + phdr->p_memsz;
577 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end)
579 } else if (phdr->p_type == PT_ARM_EXIDX) {
580 uintptr_t exidx_start = image_base + phdr->p_vaddr;
581 cbdata->sects->arm_section = exidx_start;
582 cbdata->sects->arm_section_length = phdr->p_memsz;
586 return found_obj && found_hdr;
590 return static_cast<bool>(found);
597 inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
599 return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde));
601 // TO DO: if OS has way to dynamically register FDEs, check that.
608 inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
610 unw_word_t *offset) {
611 #if _LIBUNWIND_USE_DLADDR
613 if (dladdr((void *)addr, &dyldInfo)) {
614 if (dyldInfo.dli_sname != NULL) {
615 snprintf(buf, bufLen, "%s", dyldInfo.dli_sname);
616 *offset = (addr - (pint_t) dyldInfo.dli_saddr);
629 } // namespace libunwind
631 #endif // __ADDRESSSPACE_HPP__