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 #include "libunwind.h"
23 #include "EHHeaderParser.hpp"
24 #include "Registers.hpp"
26 #ifndef _LIBUNWIND_USE_DLADDR
27 #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
28 #define _LIBUNWIND_USE_DLADDR 1
30 #define _LIBUNWIND_USE_DLADDR 0
34 #if _LIBUNWIND_USE_DLADDR
36 #if defined(__ELF__) && defined(_LIBUNWIND_LINK_DL_LIB)
37 #pragma comment(lib, "dl")
41 #if defined(_LIBUNWIND_ARM_EHABI)
42 struct EHABIIndexEntry
{
43 uint32_t functionOffset
;
50 struct dyld_unwind_sections
52 const struct mach_header
* mh
;
53 const void* dwarf_section
;
54 uintptr_t dwarf_section_length
;
55 const void* compact_unwind_section
;
56 uintptr_t compact_unwind_section_length
;
59 // In 10.7.0 or later, libSystem.dylib implements this function.
60 extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections
*);
62 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
64 // When statically linked on bare-metal, the symbols for the EH table are looked
65 // up without going through the dynamic loader.
67 // The following linker script may be used to produce the necessary sections and symbols.
68 // Unless the --eh-frame-hdr linker option is provided, the section is not generated
69 // and does not take space in the output file.
73 // __eh_frame_start = .;
75 // __eh_frame_end = .;
80 // KEEP(*(.eh_frame_hdr))
83 // __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
84 // __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
86 extern char __eh_frame_start
;
87 extern char __eh_frame_end
;
89 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
90 extern char __eh_frame_hdr_start
;
91 extern char __eh_frame_hdr_end
;
94 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
96 // When statically linked on bare-metal, the symbols for the EH table are looked
97 // up without going through the dynamic loader.
98 extern char __exidx_start
;
99 extern char __exidx_end
;
101 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
106 #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) || \
107 defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX)
113 namespace libunwind
{
115 /// Used by findUnwindSections() to return info about needed sections.
116 struct UnwindInfoSections
{
117 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || \
118 defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) || \
119 defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
120 // No dso_base for SEH.
123 #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
124 uintptr_t text_segment_length
;
126 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
127 uintptr_t dwarf_section
;
128 uintptr_t dwarf_section_length
;
130 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
131 uintptr_t dwarf_index_section
;
132 uintptr_t dwarf_index_section_length
;
134 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
135 uintptr_t compact_unwind_section
;
136 uintptr_t compact_unwind_section_length
;
138 #if defined(_LIBUNWIND_ARM_EHABI)
139 uintptr_t arm_section
;
140 uintptr_t arm_section_length
;
145 /// LocalAddressSpace is used as a template parameter to UnwindCursor when
146 /// unwinding a thread in the same process. The wrappers compile away,
147 /// making local unwinds fast.
148 class _LIBUNWIND_HIDDEN LocalAddressSpace
{
150 typedef uintptr_t pint_t
;
151 typedef intptr_t sint_t
;
152 uint8_t get8(pint_t addr
) {
154 memcpy(&val
, (void *)addr
, sizeof(val
));
157 uint16_t get16(pint_t addr
) {
159 memcpy(&val
, (void *)addr
, sizeof(val
));
162 uint32_t get32(pint_t addr
) {
164 memcpy(&val
, (void *)addr
, sizeof(val
));
167 uint64_t get64(pint_t addr
) {
169 memcpy(&val
, (void *)addr
, sizeof(val
));
172 double getDouble(pint_t addr
) {
174 memcpy(&val
, (void *)addr
, sizeof(val
));
177 v128
getVector(pint_t addr
) {
179 memcpy(&val
, (void *)addr
, sizeof(val
));
182 uintptr_t getP(pint_t addr
);
183 uint64_t getRegister(pint_t addr
);
184 static uint64_t getULEB128(pint_t
&addr
, pint_t end
);
185 static int64_t getSLEB128(pint_t
&addr
, pint_t end
);
187 pint_t
getEncodedP(pint_t
&addr
, pint_t end
, uint8_t encoding
,
188 pint_t datarelBase
= 0);
189 bool findFunctionName(pint_t addr
, char *buf
, size_t bufLen
,
191 bool findUnwindSections(pint_t targetAddr
, UnwindInfoSections
&info
);
192 bool findOtherFDE(pint_t targetAddr
, pint_t
&fde
);
194 static LocalAddressSpace sThisAddressSpace
;
197 inline uintptr_t LocalAddressSpace::getP(pint_t addr
) {
198 #if __SIZEOF_POINTER__ == 8
205 inline uint64_t LocalAddressSpace::getRegister(pint_t addr
) {
206 #if __SIZEOF_POINTER__ == 8 || defined(__mips64)
213 /// Read a ULEB128 into a 64-bit word.
214 inline uint64_t LocalAddressSpace::getULEB128(pint_t
&addr
, pint_t end
) {
215 const uint8_t *p
= (uint8_t *)addr
;
216 const uint8_t *pend
= (uint8_t *)end
;
223 _LIBUNWIND_ABORT("truncated uleb128 expression");
227 if (bit
>= 64 || b
<< bit
>> bit
!= b
) {
228 _LIBUNWIND_ABORT("malformed uleb128 expression");
233 } while (*p
++ >= 0x80);
238 /// Read a SLEB128 into a 64-bit word.
239 inline int64_t LocalAddressSpace::getSLEB128(pint_t
&addr
, pint_t end
) {
240 const uint8_t *p
= (uint8_t *)addr
;
241 const uint8_t *pend
= (uint8_t *)end
;
247 _LIBUNWIND_ABORT("truncated sleb128 expression");
249 result
|= (uint64_t)(byte
& 0x7f) << bit
;
251 } while (byte
& 0x80);
252 // sign extend negative numbers
253 if ((byte
& 0x40) != 0 && bit
< 64)
254 result
|= (-1ULL) << bit
;
259 inline LocalAddressSpace::pint_t
260 LocalAddressSpace::getEncodedP(pint_t
&addr
, pint_t end
, uint8_t encoding
,
261 pint_t datarelBase
) {
262 pint_t startAddr
= addr
;
263 const uint8_t *p
= (uint8_t *)addr
;
267 switch (encoding
& 0x0F) {
273 case DW_EH_PE_uleb128
:
274 result
= (pint_t
)getULEB128(addr
, end
);
276 case DW_EH_PE_udata2
:
277 result
= get16(addr
);
281 case DW_EH_PE_udata4
:
282 result
= get32(addr
);
286 case DW_EH_PE_udata8
:
287 result
= (pint_t
)get64(addr
);
291 case DW_EH_PE_sleb128
:
292 result
= (pint_t
)getSLEB128(addr
, end
);
294 case DW_EH_PE_sdata2
:
295 // Sign extend from signed 16-bit value.
296 result
= (pint_t
)(int16_t)get16(addr
);
300 case DW_EH_PE_sdata4
:
301 // Sign extend from signed 32-bit value.
302 result
= (pint_t
)(int32_t)get32(addr
);
306 case DW_EH_PE_sdata8
:
307 result
= (pint_t
)get64(addr
);
312 _LIBUNWIND_ABORT("unknown pointer encoding");
315 // then add relative offset
316 switch (encoding
& 0x70) {
317 case DW_EH_PE_absptr
:
323 case DW_EH_PE_textrel
:
324 _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported");
326 case DW_EH_PE_datarel
:
327 // DW_EH_PE_datarel is only valid in a few places, so the parameter has a
328 // default value of 0, and we abort in the event that someone calls this
329 // function with a datarelBase of 0 and DW_EH_PE_datarel encoding.
330 if (datarelBase
== 0)
331 _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0");
332 result
+= datarelBase
;
334 case DW_EH_PE_funcrel
:
335 _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported");
337 case DW_EH_PE_aligned
:
338 _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported");
341 _LIBUNWIND_ABORT("unknown pointer encoding");
345 if (encoding
& DW_EH_PE_indirect
)
346 result
= getP(result
);
351 #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
353 // The ElfW() macro for pointer-size independent ELF header traversal is not
354 // provided by <link.h> on some systems (e.g., FreeBSD). On these systems the
355 // data structures are just called Elf_XXX. Define ElfW() locally.
357 #define ElfW(type) Elf_##type
359 #if !defined(Elf_Half)
360 typedef ElfW(Half
) Elf_Half
;
362 #if !defined(Elf_Phdr)
363 typedef ElfW(Phdr
) Elf_Phdr
;
365 #if !defined(Elf_Addr)
366 typedef ElfW(Addr
) Elf_Addr
;
369 static Elf_Addr
calculateImageBase(struct dl_phdr_info
*pinfo
) {
370 Elf_Addr image_base
= pinfo
->dlpi_addr
;
371 #if defined(__ANDROID__) && __ANDROID_API__ < 18
372 if (image_base
== 0) {
373 // Normally, an image base of 0 indicates a non-PIE executable. On
374 // versions of Android prior to API 18, the dynamic linker reported a
375 // dlpi_addr of 0 for PIE executables. Compute the true image base
376 // using the PT_PHDR segment.
377 // See https://github.com/android/ndk/issues/505.
378 for (Elf_Half i
= 0; i
< pinfo
->dlpi_phnum
; i
++) {
379 const Elf_Phdr
*phdr
= &pinfo
->dlpi_phdr
[i
];
380 if (phdr
->p_type
== PT_PHDR
) {
381 image_base
= reinterpret_cast<Elf_Addr
>(pinfo
->dlpi_phdr
) -
391 struct _LIBUNWIND_HIDDEN dl_iterate_cb_data
{
392 LocalAddressSpace
*addressSpace
;
393 UnwindInfoSections
*sects
;
394 uintptr_t targetAddr
;
397 #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE)
398 #include "FrameHeaderCache.hpp"
400 // Typically there is one cache per process, but when libunwind is built as a
401 // hermetic static library, then each shared object may have its own cache.
402 static FrameHeaderCache TheFrameHeaderCache
;
405 static bool checkAddrInSegment(const Elf_Phdr
*phdr
, size_t image_base
,
406 dl_iterate_cb_data
*cbdata
) {
407 if (phdr
->p_type
== PT_LOAD
) {
408 uintptr_t begin
= image_base
+ phdr
->p_vaddr
;
409 uintptr_t end
= begin
+ phdr
->p_memsz
;
410 if (cbdata
->targetAddr
>= begin
&& cbdata
->targetAddr
< end
) {
411 cbdata
->sects
->dso_base
= begin
;
412 cbdata
->sects
->text_segment_length
= phdr
->p_memsz
;
419 static bool checkForUnwindInfoSegment(const Elf_Phdr
*phdr
, size_t image_base
,
420 dl_iterate_cb_data
*cbdata
) {
421 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
422 if (phdr
->p_type
== PT_GNU_EH_FRAME
) {
423 EHHeaderParser
<LocalAddressSpace
>::EHHeaderInfo hdrInfo
;
424 uintptr_t eh_frame_hdr_start
= image_base
+ phdr
->p_vaddr
;
425 cbdata
->sects
->dwarf_index_section
= eh_frame_hdr_start
;
426 cbdata
->sects
->dwarf_index_section_length
= phdr
->p_memsz
;
427 if (EHHeaderParser
<LocalAddressSpace
>::decodeEHHdr(
428 *cbdata
->addressSpace
, eh_frame_hdr_start
, phdr
->p_memsz
,
430 // .eh_frame_hdr records the start of .eh_frame, but not its size.
431 // Rely on a zero terminator to find the end of the section.
432 cbdata
->sects
->dwarf_section
= hdrInfo
.eh_frame_ptr
;
433 cbdata
->sects
->dwarf_section_length
= UINTPTR_MAX
;
438 #elif defined(_LIBUNWIND_ARM_EHABI)
439 if (phdr
->p_type
== PT_ARM_EXIDX
) {
440 uintptr_t exidx_start
= image_base
+ phdr
->p_vaddr
;
441 cbdata
->sects
->arm_section
= exidx_start
;
442 cbdata
->sects
->arm_section_length
= phdr
->p_memsz
;
447 #error Need one of _LIBUNWIND_SUPPORT_DWARF_INDEX or _LIBUNWIND_ARM_EHABI
451 static int findUnwindSectionsByPhdr(struct dl_phdr_info
*pinfo
,
452 size_t pinfo_size
, void *data
) {
453 auto cbdata
= static_cast<dl_iterate_cb_data
*>(data
);
454 if (pinfo
->dlpi_phnum
== 0 || cbdata
->targetAddr
< pinfo
->dlpi_addr
)
456 #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE)
457 if (TheFrameHeaderCache
.find(pinfo
, pinfo_size
, data
))
460 // Avoid warning about unused variable.
464 Elf_Addr image_base
= calculateImageBase(pinfo
);
466 // Most shared objects seen in this callback function likely don't contain the
467 // target address, so optimize for that. Scan for a matching PT_LOAD segment
468 // first and bail when it isn't found.
469 bool found_text
= false;
470 for (Elf_Half i
= 0; i
< pinfo
->dlpi_phnum
; ++i
) {
471 if (checkAddrInSegment(&pinfo
->dlpi_phdr
[i
], image_base
, cbdata
)) {
479 // PT_GNU_EH_FRAME and PT_ARM_EXIDX are usually near the end. Iterate
481 bool found_unwind
= false;
482 for (Elf_Half i
= pinfo
->dlpi_phnum
; i
> 0; i
--) {
483 const Elf_Phdr
*phdr
= &pinfo
->dlpi_phdr
[i
- 1];
484 if (checkForUnwindInfoSegment(phdr
, image_base
, cbdata
)) {
492 #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE)
493 TheFrameHeaderCache
.add(cbdata
->sects
);
498 #endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
501 inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr
,
502 UnwindInfoSections
&info
) {
504 dyld_unwind_sections dyldInfo
;
505 if (_dyld_find_unwind_sections((void *)targetAddr
, &dyldInfo
)) {
506 info
.dso_base
= (uintptr_t)dyldInfo
.mh
;
507 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
508 info
.dwarf_section
= (uintptr_t)dyldInfo
.dwarf_section
;
509 info
.dwarf_section_length
= dyldInfo
.dwarf_section_length
;
511 info
.compact_unwind_section
= (uintptr_t)dyldInfo
.compact_unwind_section
;
512 info
.compact_unwind_section_length
= dyldInfo
.compact_unwind_section_length
;
515 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
517 // Bare metal is statically linked, so no need to ask the dynamic loader
518 info
.dwarf_section_length
= (uintptr_t)(&__eh_frame_end
- &__eh_frame_start
);
519 info
.dwarf_section
= (uintptr_t)(&__eh_frame_start
);
520 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
521 (void *)info
.dwarf_section
, (void *)info
.dwarf_section_length
);
522 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
523 info
.dwarf_index_section
= (uintptr_t)(&__eh_frame_hdr_start
);
524 info
.dwarf_index_section_length
= (uintptr_t)(&__eh_frame_hdr_end
- &__eh_frame_hdr_start
);
525 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p",
526 (void *)info
.dwarf_index_section
, (void *)info
.dwarf_index_section_length
);
528 if (info
.dwarf_section_length
)
530 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
531 // Bare metal is statically linked, so no need to ask the dynamic loader
532 info
.arm_section
= (uintptr_t)(&__exidx_start
);
533 info
.arm_section_length
= (uintptr_t)(&__exidx_end
- &__exidx_start
);
534 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
535 (void *)info
.arm_section
, (void *)info
.arm_section_length
);
536 if (info
.arm_section
&& info
.arm_section_length
)
538 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
540 HANDLE process
= GetCurrentProcess();
543 if (!EnumProcessModules(process
, mods
, sizeof(mods
), &needed
)) {
544 DWORD err
= GetLastError();
545 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: EnumProcessModules failed, "
546 "returned error %d", (int)err
);
550 for (unsigned i
= 0; i
< (needed
/ sizeof(HMODULE
)); i
++) {
551 PIMAGE_DOS_HEADER pidh
= (PIMAGE_DOS_HEADER
)mods
[i
];
552 PIMAGE_NT_HEADERS pinh
= (PIMAGE_NT_HEADERS
)((BYTE
*)pidh
+ pidh
->e_lfanew
);
553 PIMAGE_FILE_HEADER pifh
= (PIMAGE_FILE_HEADER
)&pinh
->FileHeader
;
554 PIMAGE_SECTION_HEADER pish
= IMAGE_FIRST_SECTION(pinh
);
555 bool found_obj
= false;
556 bool found_hdr
= false;
558 info
.dso_base
= (uintptr_t)mods
[i
];
559 for (unsigned j
= 0; j
< pifh
->NumberOfSections
; j
++, pish
++) {
560 uintptr_t begin
= pish
->VirtualAddress
+ (uintptr_t)mods
[i
];
561 uintptr_t end
= begin
+ pish
->Misc
.VirtualSize
;
562 if (!strncmp((const char *)pish
->Name
, ".text",
563 IMAGE_SIZEOF_SHORT_NAME
)) {
564 if (targetAddr
>= begin
&& targetAddr
< end
)
566 } else if (!strncmp((const char *)pish
->Name
, ".eh_frame",
567 IMAGE_SIZEOF_SHORT_NAME
)) {
568 info
.dwarf_section
= begin
;
569 info
.dwarf_section_length
= pish
->Misc
.VirtualSize
;
572 if (found_obj
&& found_hdr
)
577 #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
578 // Don't even bother, since Windows has functions that do all this stuff
583 #elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX)
586 (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr
)targetAddr
, &length
);
587 info
.arm_section_length
= (uintptr_t)length
* sizeof(EHABIIndexEntry
);
588 if (info
.arm_section
&& info
.arm_section_length
)
590 #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
591 dl_iterate_cb_data cb_data
= {this, &info
, targetAddr
};
592 int found
= dl_iterate_phdr(findUnwindSectionsByPhdr
, &cb_data
);
593 return static_cast<bool>(found
);
600 inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr
, pint_t
&fde
) {
601 // TO DO: if OS has way to dynamically register FDEs, check that.
607 inline bool LocalAddressSpace::findFunctionName(pint_t addr
, char *buf
,
609 unw_word_t
*offset
) {
610 #if _LIBUNWIND_USE_DLADDR
612 if (dladdr((void *)addr
, &dyldInfo
)) {
613 if (dyldInfo
.dli_sname
!= NULL
) {
614 snprintf(buf
, bufLen
, "%s", dyldInfo
.dli_sname
);
615 *offset
= (addr
- (pint_t
) dyldInfo
.dli_saddr
);
628 } // namespace libunwind
630 #endif // __ADDRESSSPACE_HPP__