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 54namespace __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