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