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