Home | History | Annotate | Download | only in src
      1 // Copyright (C) 2012 The Android Open Source Project
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions
      6 // are met:
      7 // 1. Redistributions of source code must retain the above copyright
      8 //    notice, this list of conditions and the following disclaimer.
      9 // 2. Redistributions in binary form must reproduce the above copyright
     10 //    notice, this list of conditions and the following disclaimer in the
     11 //    documentation and/or other materials provided with the distribution.
     12 // 3. Neither the name of the project nor the names of its contributors
     13 //    may be used to endorse or promote products derived from this software
     14 //    without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19 // ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26 // SUCH DAMAGE.
     27 //===----------------------------------------------------------------------===//
     28 //
     29 //                     The LLVM Compiler Infrastructure
     30 //
     31 // This file is dual licensed under the MIT and the University of Illinois Open
     32 // Source Licenses. See LICENSE.TXT for details.
     33 //
     34 //
     35 //  This file implements the "Exception Handling APIs"
     36 //  http://www.codesourcery.com/public/cxx-abi/abi-eh.html
     37 //  http://www.intel.com/design/itanium/downloads/245358.htm
     38 //
     39 //===----------------------------------------------------------------------===//
     40 
     41 #include <cstdlib>
     42 #include <endian.h>
     43 #include "dwarf_helper.h"
     44 
     45 #if !defined(__BYTE_ORDER) || \
     46     !defined(__LITTLE_ENDIAN) || !defined(__BIG_ENDIAN)
     47 #error "Endianness testing macros are not defined"
     48 #endif
     49 
     50 #if __BYTE_ORDER != __LITTLE_ENDIAN && __BYTE_ORDER != __BIG_ENDIAN
     51 #error "Unsupported endianness"
     52 #endif
     53 
     54 namespace __cxxabiv1 {
     55 
     56   uintptr_t readULEB128(const uint8_t** data) {
     57     uintptr_t result = 0;
     58     uintptr_t shift = 0;
     59     unsigned char byte;
     60     const uint8_t *p = *data;
     61     do {
     62       byte = *p++;
     63       result |= static_cast<uintptr_t>(byte & 0x7F) << shift;
     64       shift += 7;
     65     } while (byte & 0x80);
     66     *data = p;
     67     return result;
     68   }
     69 
     70   intptr_t readSLEB128(const uint8_t** data) {
     71     uintptr_t result = 0;
     72     uintptr_t shift = 0;
     73     unsigned char byte;
     74     const uint8_t *p = *data;
     75     do {
     76       byte = *p++;
     77       result |= static_cast<uintptr_t>(byte & 0x7F) << shift;
     78       shift += 7;
     79     } while (byte & 0x80);
     80     *data = p;
     81     if ((byte & 0x40) && (shift < (sizeof(result) << 3))) {
     82       result |= static_cast<uintptr_t>(~0) << shift;
     83     }
     84     return static_cast<intptr_t>(result);
     85   }
     86 
     87   static inline uint16_t readUData2(const uint8_t* data) {
     88 #if __BYTE_ORDER == __LITTLE_ENDIAN
     89     return ((static_cast<uint16_t>(data[0])) |
     90             (static_cast<uint16_t>(data[1]) << 8));
     91 #elif __BYTE_ORDER == __BIG_ENDIAN
     92     return ((static_cast<uint16_t>(data[0]) << 8) |
     93             (static_cast<uint16_t>(data[1])));
     94 #endif
     95   }
     96 
     97   static inline uint32_t readUData4(const uint8_t* data) {
     98 #if __BYTE_ORDER == __LITTLE_ENDIAN
     99     return ((static_cast<uint32_t>(data[0])) |
    100             (static_cast<uint32_t>(data[1]) << 8) |
    101             (static_cast<uint32_t>(data[2]) << 16) |
    102             (static_cast<uint32_t>(data[3]) << 24));
    103 #elif __BYTE_ORDER == __BIG_ENDIAN
    104     return ((static_cast<uint32_t>(data[0]) << 24) |
    105             (static_cast<uint32_t>(data[1]) << 16) |
    106             (static_cast<uint32_t>(data[2]) << 8) |
    107             (static_cast<uint32_t>(data[3])));
    108 #endif
    109   }
    110 
    111   static inline uint64_t readUData8(const uint8_t* data) {
    112 #if __BYTE_ORDER == __LITTLE_ENDIAN
    113     return ((static_cast<uint64_t>(data[0])) |
    114             (static_cast<uint64_t>(data[1]) << 8) |
    115             (static_cast<uint64_t>(data[2]) << 16) |
    116             (static_cast<uint64_t>(data[3]) << 24) |
    117             (static_cast<uint64_t>(data[4]) << 32) |
    118             (static_cast<uint64_t>(data[5]) << 40) |
    119             (static_cast<uint64_t>(data[6]) << 48) |
    120             (static_cast<uint64_t>(data[7]) << 56));
    121 #elif __BYTE_ORDER == __BIG_ENDIAN
    122     return ((static_cast<uint64_t>(data[0]) << 56) |
    123             (static_cast<uint64_t>(data[1]) << 48) |
    124             (static_cast<uint64_t>(data[2]) << 40) |
    125             (static_cast<uint64_t>(data[3]) << 32) |
    126             (static_cast<uint64_t>(data[4]) << 24) |
    127             (static_cast<uint64_t>(data[5]) << 16) |
    128             (static_cast<uint64_t>(data[6]) << 8) |
    129             (static_cast<uint64_t>(data[7])));
    130 #endif
    131   }
    132 
    133   static inline uintptr_t readAbsPtr(const uint8_t* data) {
    134     if (sizeof(uintptr_t) == 4) {
    135       return static_cast<uintptr_t>(readUData4(data));
    136     } else if (sizeof(uintptr_t) == 8) {
    137       return static_cast<uintptr_t>(readUData8(data));
    138     } else {
    139       abort();
    140     }
    141   }
    142 
    143   uintptr_t readEncodedPointer(const uint8_t** data,
    144                                uint8_t encoding) {
    145     uintptr_t result = 0;
    146     if (encoding == DW_EH_PE_omit) {
    147       return result;
    148     }
    149     const uint8_t* p = *data;
    150 
    151     switch (encoding & 0x0F) {
    152     default:
    153       abort();
    154       break;
    155     case DW_EH_PE_absptr:
    156       result = readAbsPtr(p);
    157       p += sizeof(uintptr_t);
    158       break;
    159     case DW_EH_PE_uleb128:
    160       result = readULEB128(&p);
    161       break;
    162     case DW_EH_PE_sleb128:
    163       result = static_cast<uintptr_t>(readSLEB128(&p));
    164       break;
    165     case DW_EH_PE_udata2:
    166       result = readUData2(p);
    167       p += sizeof(uint16_t);
    168       break;
    169     case DW_EH_PE_udata4:
    170       result = readUData4(p);
    171       p += sizeof(uint32_t);
    172       break;
    173     case DW_EH_PE_udata8:
    174       result = static_cast<uintptr_t>(readUData8(p));
    175       p += sizeof(uint64_t);
    176       break;
    177     case DW_EH_PE_sdata2:
    178       result = static_cast<uintptr_t>(static_cast<int16_t>(readUData2(p)));
    179       p += sizeof(int16_t);
    180       break;
    181     case DW_EH_PE_sdata4:
    182       result = static_cast<uintptr_t>(static_cast<int32_t>(readUData4(p)));
    183       p += sizeof(int32_t);
    184       break;
    185     case DW_EH_PE_sdata8:
    186       result = static_cast<uintptr_t>(static_cast<int64_t>(readUData8(p)));
    187       p += sizeof(int64_t);
    188       break;
    189     }
    190 
    191     switch (encoding & 0x70) {
    192     default:
    193       abort();
    194       break;
    195     case DW_EH_PE_absptr:
    196       break;
    197     case DW_EH_PE_pcrel:
    198       if (result) {
    199         result += (uintptr_t)(*data);
    200       }
    201       break;
    202     }
    203 
    204     // finally, apply indirection
    205     if (result && (encoding & DW_EH_PE_indirect)) {
    206       result = *(reinterpret_cast<uintptr_t*>(result));
    207     }
    208     *data = p;
    209     return result;
    210   }
    211 
    212 } // namespace __cxxabiv1
    213