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 #ifndef _LIBUNWIND_IS_BAREMETAL
22 #include <dlfcn.h>
23 #endif
24 
25 #ifdef __APPLE__
26 #include <mach-o/getsect.h>
27 namespace libunwind {
28    bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde);
29 }
30 #endif
31 
32 #include "libunwind.h"
33 #include "config.h"
34 #include "dwarf2.h"
35 #include "Registers.hpp"
36 
37 #if _LIBUNWIND_ARM_EHABI
38 #ifdef __linux__
39 
40 typedef long unsigned int *_Unwind_Ptr;
41 extern "C" _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr addr, int *len);
42 
43 // Emulate the BSD dl_unwind_find_exidx API when on a GNU libdl system.
44 #define dl_unwind_find_exidx __gnu_Unwind_Find_exidx
45 
46 #elif !defined(_LIBUNWIND_IS_BAREMETAL)
47 #include <link.h>
48 #else // !defined(_LIBUNWIND_IS_BAREMETAL)
49 // When statically linked on bare-metal, the symbols for the EH table are looked
50 // up without going through the dynamic loader.
51 struct EHTEntry {
52   uint32_t functionOffset;
53   uint32_t unwindOpcodes;
54 };
55 extern EHTEntry __exidx_start;
56 extern EHTEntry __exidx_end;
57 #endif // !defined(_LIBUNWIND_IS_BAREMETAL)
58 #endif // _LIBUNWIND_ARM_EHABI
59 
60 #if defined(__CloudABI__) || defined(__FreeBSD__) || defined(__linux__)
61 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND && _LIBUNWIND_SUPPORT_DWARF_INDEX
62 #include <link.h>
63 // Macro for machine-independent access to the ELF program headers. This
64 // macro is not available on some systems (e.g., FreeBSD). On these
65 // systems the data structures are just called Elf_XXX. Define ElfW()
66 // locally.
67 #if !defined(ElfW)
68 #define ElfW(type) Elf_##type
69 #endif
70 #include "EHHeaderParser.hpp"
71 #endif
72 #endif
73 
74 namespace libunwind {
75 
76 /// Used by findUnwindSections() to return info about needed sections.
77 struct UnwindInfoSections {
78 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND || _LIBUNWIND_SUPPORT_DWARF_INDEX ||       \
79     _LIBUNWIND_SUPPORT_COMPACT_UNWIND
80   // No dso_base for ARM EHABI.
81   uintptr_t       dso_base;
82 #endif
83 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
84   uintptr_t       dwarf_section;
85   uintptr_t       dwarf_section_length;
86 #endif
87 #if _LIBUNWIND_SUPPORT_DWARF_INDEX
88   uintptr_t       dwarf_index_section;
89   uintptr_t       dwarf_index_section_length;
90 #endif
91 #if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
92   uintptr_t       compact_unwind_section;
93   uintptr_t       compact_unwind_section_length;
94 #endif
95 #if _LIBUNWIND_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 #ifdef __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
get8(pint_t addr)114   uint8_t         get8(pint_t addr) {
115     uint8_t val;
116     memcpy(&val, (void *)addr, sizeof(val));
117     return val;
118   }
get16(pint_t addr)119   uint16_t         get16(pint_t addr) {
120     uint16_t val;
121     memcpy(&val, (void *)addr, sizeof(val));
122     return val;
123   }
get32(pint_t addr)124   uint32_t         get32(pint_t addr) {
125     uint32_t val;
126     memcpy(&val, (void *)addr, sizeof(val));
127     return val;
128   }
get64(pint_t addr)129   uint64_t         get64(pint_t addr) {
130     uint64_t val;
131     memcpy(&val, (void *)addr, sizeof(val));
132     return val;
133   }
getDouble(pint_t addr)134   double           getDouble(pint_t addr) {
135     double val;
136     memcpy(&val, (void *)addr, sizeof(val));
137     return val;
138   }
getVector(pint_t addr)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                      pint_t datarelBase = 0);
150   bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
151                         unw_word_t *offset);
152   bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
153   bool findOtherFDE(pint_t targetAddr, pint_t &fde);
154 
155   static LocalAddressSpace sThisAddressSpace;
156 };
157 
getP(pint_t addr)158 inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
159 #ifdef __LP64__
160   return get64(addr);
161 #else
162   return get32(addr);
163 #endif
164 }
165 
166 /// Read a ULEB128 into a 64-bit word.
getULEB128(pint_t & addr,pint_t end)167 inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
168   const uint8_t *p = (uint8_t *)addr;
169   const uint8_t *pend = (uint8_t *)end;
170   uint64_t result = 0;
171   int bit = 0;
172   do {
173     uint64_t b;
174 
175     if (p == pend)
176       _LIBUNWIND_ABORT("truncated uleb128 expression");
177 
178     b = *p & 0x7f;
179 
180     if (bit >= 64 || b << bit >> bit != b) {
181       _LIBUNWIND_ABORT("malformed uleb128 expression");
182     } else {
183       result |= b << bit;
184       bit += 7;
185     }
186   } while (*p++ >= 0x80);
187   addr = (pint_t) p;
188   return result;
189 }
190 
191 /// Read a SLEB128 into a 64-bit word.
getSLEB128(pint_t & addr,pint_t end)192 inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
193   const uint8_t *p = (uint8_t *)addr;
194   const uint8_t *pend = (uint8_t *)end;
195   int64_t result = 0;
196   int bit = 0;
197   uint8_t byte;
198   do {
199     if (p == pend)
200       _LIBUNWIND_ABORT("truncated sleb128 expression");
201     byte = *p++;
202     result |= ((byte & 0x7f) << bit);
203     bit += 7;
204   } while (byte & 0x80);
205   // sign extend negative numbers
206   if ((byte & 0x40) != 0)
207     result |= (-1LL) << bit;
208   addr = (pint_t) p;
209   return result;
210 }
211 
212 inline LocalAddressSpace::pint_t
getEncodedP(pint_t & addr,pint_t end,uint8_t encoding,pint_t datarelBase)213 LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
214                                pint_t datarelBase) {
215   pint_t startAddr = addr;
216   const uint8_t *p = (uint8_t *)addr;
217   pint_t result;
218 
219   // first get value
220   switch (encoding & 0x0F) {
221   case DW_EH_PE_ptr:
222     result = getP(addr);
223     p += sizeof(pint_t);
224     addr = (pint_t) p;
225     break;
226   case DW_EH_PE_uleb128:
227     result = (pint_t)getULEB128(addr, end);
228     break;
229   case DW_EH_PE_udata2:
230     result = get16(addr);
231     p += 2;
232     addr = (pint_t) p;
233     break;
234   case DW_EH_PE_udata4:
235     result = get32(addr);
236     p += 4;
237     addr = (pint_t) p;
238     break;
239   case DW_EH_PE_udata8:
240     result = (pint_t)get64(addr);
241     p += 8;
242     addr = (pint_t) p;
243     break;
244   case DW_EH_PE_sleb128:
245     result = (pint_t)getSLEB128(addr, end);
246     break;
247   case DW_EH_PE_sdata2:
248     // Sign extend from signed 16-bit value.
249     result = (pint_t)(int16_t)get16(addr);
250     p += 2;
251     addr = (pint_t) p;
252     break;
253   case DW_EH_PE_sdata4:
254     // Sign extend from signed 32-bit value.
255     result = (pint_t)(int32_t)get32(addr);
256     p += 4;
257     addr = (pint_t) p;
258     break;
259   case DW_EH_PE_sdata8:
260     result = (pint_t)get64(addr);
261     p += 8;
262     addr = (pint_t) p;
263     break;
264   default:
265     _LIBUNWIND_ABORT("unknown pointer encoding");
266   }
267 
268   // then add relative offset
269   switch (encoding & 0x70) {
270   case DW_EH_PE_absptr:
271     // do nothing
272     break;
273   case DW_EH_PE_pcrel:
274     result += startAddr;
275     break;
276   case DW_EH_PE_textrel:
277     _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported");
278     break;
279   case DW_EH_PE_datarel:
280     // DW_EH_PE_datarel is only valid in a few places, so the parameter has a
281     // default value of 0, and we abort in the event that someone calls this
282     // function with a datarelBase of 0 and DW_EH_PE_datarel encoding.
283     if (datarelBase == 0)
284       _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0");
285     result += datarelBase;
286     break;
287   case DW_EH_PE_funcrel:
288     _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported");
289     break;
290   case DW_EH_PE_aligned:
291     _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported");
292     break;
293   default:
294     _LIBUNWIND_ABORT("unknown pointer encoding");
295     break;
296   }
297 
298   if (encoding & DW_EH_PE_indirect)
299     result = getP(result);
300 
301   return result;
302 }
303 
304 #ifdef __APPLE__
305   struct dyld_unwind_sections
306   {
307     const struct mach_header*   mh;
308     const void*                 dwarf_section;
309     uintptr_t                   dwarf_section_length;
310     const void*                 compact_unwind_section;
311     uintptr_t                   compact_unwind_section_length;
312   };
313   #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
314                                  && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \
315       || defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
316     // In 10.7.0 or later, libSystem.dylib implements this function.
317     extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
318   #else
319     // In 10.6.x and earlier, we need to implement this functionality.
_dyld_find_unwind_sections(void * addr,dyld_unwind_sections * info)320     static inline bool _dyld_find_unwind_sections(void* addr,
321                                                     dyld_unwind_sections* info) {
322       // Find mach-o image containing address.
323       Dl_info dlinfo;
324       if (!dladdr(addr, &dlinfo))
325         return false;
326       const mach_header *mh = (const mach_header *)dlinfo.dli_saddr;
327 
328       // Find dwarf unwind section in that image.
329       unsigned long size;
330       const uint8_t *p = getsectiondata(mh, "__TEXT", "__eh_frame", &size);
331       if (!p)
332         return false;
333 
334       // Fill in return struct.
335       info->mh = mh;
336       info->dwarf_section = p;
337       info->dwarf_section_length = size;
338       info->compact_unwind_section = 0;
339       info->compact_unwind_section_length = 0;
340 
341       return true;
342     }
343   #endif
344 #endif
345 
findUnwindSections(pint_t targetAddr,UnwindInfoSections & info)346 inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
347                                                   UnwindInfoSections &info) {
348 #ifdef __APPLE__
349   dyld_unwind_sections dyldInfo;
350   if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
351     info.dso_base                      = (uintptr_t)dyldInfo.mh;
352  #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
353     info.dwarf_section                 = (uintptr_t)dyldInfo.dwarf_section;
354     info.dwarf_section_length          = dyldInfo.dwarf_section_length;
355  #endif
356     info.compact_unwind_section        = (uintptr_t)dyldInfo.compact_unwind_section;
357     info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
358     return true;
359   }
360 #elif _LIBUNWIND_ARM_EHABI
361  #ifdef _LIBUNWIND_IS_BAREMETAL
362   // Bare metal is statically linked, so no need to ask the dynamic loader
363   info.arm_section =        (uintptr_t)(&__exidx_start);
364   info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start);
365  #else
366   int length = 0;
367   info.arm_section = (uintptr_t) dl_unwind_find_exidx(
368       (_Unwind_Ptr) targetAddr, &length);
369   info.arm_section_length = (uintptr_t)length;
370  #endif
371   _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x\n",
372                              info.arm_section, info.arm_section_length);
373   if (info.arm_section && info.arm_section_length)
374     return true;
375 #elif _LIBUNWIND_SUPPORT_DWARF_UNWIND
376 #if _LIBUNWIND_SUPPORT_DWARF_INDEX
377   struct dl_iterate_cb_data {
378     LocalAddressSpace *addressSpace;
379     UnwindInfoSections *sects;
380     uintptr_t targetAddr;
381   };
382 
383   dl_iterate_cb_data cb_data = {this, &info, targetAddr};
384   int found = dl_iterate_phdr(
385       [](struct dl_phdr_info *pinfo, size_t, void *data) -> int {
386         auto cbdata = static_cast<dl_iterate_cb_data *>(data);
387         size_t object_length;
388         bool found_obj = false;
389         bool found_hdr = false;
390 
391         assert(cbdata);
392         assert(cbdata->sects);
393 
394         if (cbdata->targetAddr < pinfo->dlpi_addr) {
395           return false;
396         }
397 
398 #if !defined(Elf_Half)
399         typedef ElfW(Half) Elf_Half;
400 #endif
401 #if !defined(Elf_Phdr)
402         typedef ElfW(Phdr) Elf_Phdr;
403 #endif
404 
405         for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
406           const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
407           if (phdr->p_type == PT_LOAD) {
408             uintptr_t begin = pinfo->dlpi_addr + 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               object_length = phdr->p_memsz;
413               found_obj = true;
414             }
415           } else if (phdr->p_type == PT_GNU_EH_FRAME) {
416             EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
417             uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr;
418             cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
419             cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
420             EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
421                 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
422                 hdrInfo);
423             cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
424             found_hdr = true;
425           }
426         }
427 
428         if (found_obj && found_hdr) {
429           cbdata->sects->dwarf_section_length = object_length;
430           return true;
431         } else {
432           return false;
433         }
434       },
435       &cb_data);
436   return static_cast<bool>(found);
437 #else
438 #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
439 #endif
440 #endif
441 
442   return false;
443 }
444 
445 
findOtherFDE(pint_t targetAddr,pint_t & fde)446 inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
447 #ifdef __APPLE__
448   return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde));
449 #else
450   // TO DO: if OS has way to dynamically register FDEs, check that.
451   (void)targetAddr;
452   (void)fde;
453   return false;
454 #endif
455 }
456 
findFunctionName(pint_t addr,char * buf,size_t bufLen,unw_word_t * offset)457 inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
458                                                 size_t bufLen,
459                                                 unw_word_t *offset) {
460 #ifndef _LIBUNWIND_IS_BAREMETAL
461   Dl_info dyldInfo;
462   if (dladdr((void *)addr, &dyldInfo)) {
463     if (dyldInfo.dli_sname != NULL) {
464       snprintf(buf, bufLen, "%s", dyldInfo.dli_sname);
465       *offset = (addr - (pint_t) dyldInfo.dli_saddr);
466       return true;
467     }
468   }
469 #endif
470   return false;
471 }
472 
473 
474 
475 #ifdef UNW_REMOTE
476 
477 /// OtherAddressSpace is used as a template parameter to UnwindCursor when
478 /// unwinding a thread in the another process.  The other process can be a
479 /// different endianness and a different pointer size which is handled by
480 /// the P template parameter.
481 template <typename P>
482 class OtherAddressSpace {
483 public:
OtherAddressSpace(task_t task)484   OtherAddressSpace(task_t task) : fTask(task) {}
485 
486   typedef typename P::uint_t pint_t;
487 
488   uint8_t   get8(pint_t addr);
489   uint16_t  get16(pint_t addr);
490   uint32_t  get32(pint_t addr);
491   uint64_t  get64(pint_t addr);
492   pint_t    getP(pint_t addr);
493   uint64_t  getULEB128(pint_t &addr, pint_t end);
494   int64_t   getSLEB128(pint_t &addr, pint_t end);
495   pint_t    getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
496                         pint_t datarelBase = 0);
497   bool      findFunctionName(pint_t addr, char *buf, size_t bufLen,
498                         unw_word_t *offset);
499   bool      findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
500   bool      findOtherFDE(pint_t targetAddr, pint_t &fde);
501 private:
502   void *localCopy(pint_t addr);
503 
504   task_t fTask;
505 };
506 
get8(pint_t addr)507 template <typename P> uint8_t OtherAddressSpace<P>::get8(pint_t addr) {
508   return *((uint8_t *)localCopy(addr));
509 }
510 
get16(pint_t addr)511 template <typename P> uint16_t OtherAddressSpace<P>::get16(pint_t addr) {
512   return P::E::get16(*(uint16_t *)localCopy(addr));
513 }
514 
get32(pint_t addr)515 template <typename P> uint32_t OtherAddressSpace<P>::get32(pint_t addr) {
516   return P::E::get32(*(uint32_t *)localCopy(addr));
517 }
518 
get64(pint_t addr)519 template <typename P> uint64_t OtherAddressSpace<P>::get64(pint_t addr) {
520   return P::E::get64(*(uint64_t *)localCopy(addr));
521 }
522 
523 template <typename P>
getP(pint_t addr)524 typename P::uint_t OtherAddressSpace<P>::getP(pint_t addr) {
525   return P::getP(*(uint64_t *)localCopy(addr));
526 }
527 
528 template <typename P>
getULEB128(pint_t & addr,pint_t end)529 uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
530   uintptr_t size = (end - addr);
531   LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
532   LocalAddressSpace::pint_t sladdr = laddr;
533   uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size);
534   addr += (laddr - sladdr);
535   return result;
536 }
537 
538 template <typename P>
getSLEB128(pint_t & addr,pint_t end)539 int64_t OtherAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
540   uintptr_t size = (end - addr);
541   LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
542   LocalAddressSpace::pint_t sladdr = laddr;
543   uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size);
544   addr += (laddr - sladdr);
545   return result;
546 }
547 
localCopy(pint_t addr)548 template <typename P> void *OtherAddressSpace<P>::localCopy(pint_t addr) {
549   // FIX ME
550 }
551 
552 template <typename P>
findFunctionName(pint_t addr,char * buf,size_t bufLen,unw_word_t * offset)553 bool OtherAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
554                                             size_t bufLen, unw_word_t *offset) {
555   // FIX ME
556 }
557 
558 /// unw_addr_space is the base class that abstract unw_addr_space_t type in
559 /// libunwind.h points to.
560 struct unw_addr_space {
561   cpu_type_t cpuType;
562   task_t taskPort;
563 };
564 
565 /// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points
566 /// to when examining
567 /// a 32-bit intel process.
568 struct unw_addr_space_i386 : public unw_addr_space {
unw_addr_space_i386libunwind::unw_addr_space_i386569   unw_addr_space_i386(task_t task) : oas(task) {}
570   OtherAddressSpace<Pointer32<LittleEndian> > oas;
571 };
572 
573 /// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
574 /// points to when examining
575 /// a 64-bit intel process.
576 struct unw_addr_space_x86_64 : public unw_addr_space {
unw_addr_space_x86_64libunwind::unw_addr_space_x86_64577   unw_addr_space_x86_64(task_t task) : oas(task) {}
578   OtherAddressSpace<Pointer64<LittleEndian> > oas;
579 };
580 
581 /// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
582 /// to when examining
583 /// a 32-bit PowerPC process.
584 struct unw_addr_space_ppc : public unw_addr_space {
unw_addr_space_ppclibunwind::unw_addr_space_ppc585   unw_addr_space_ppc(task_t task) : oas(task) {}
586   OtherAddressSpace<Pointer32<BigEndian> > oas;
587 };
588 
589 #endif // UNW_REMOTE
590 
591 } // namespace libunwind
592 
593 #endif // __ADDRESSSPACE_HPP__
594