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