• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
readULEB128(const uint8_t ** data)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 
readSLEB128(const uint8_t ** data)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 
readUData2(const uint8_t * data)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 
readUData4(const uint8_t * data)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 
readUData8(const uint8_t * data)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 
readAbsPtr(const uint8_t * data)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 
readEncodedPointer(const uint8_t ** data,uint8_t encoding)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