1ccec91a1Sjoerg /*
2ccec91a1Sjoerg * Copyright 2010-2011 PathScale, Inc. All rights reserved.
3ccec91a1Sjoerg *
4ccec91a1Sjoerg * Redistribution and use in source and binary forms, with or without
5ccec91a1Sjoerg * modification, are permitted provided that the following conditions are met:
6ccec91a1Sjoerg *
7ccec91a1Sjoerg * 1. Redistributions of source code must retain the above copyright notice,
8ccec91a1Sjoerg * this list of conditions and the following disclaimer.
9ccec91a1Sjoerg *
10ccec91a1Sjoerg * 2. Redistributions in binary form must reproduce the above copyright notice,
11ccec91a1Sjoerg * this list of conditions and the following disclaimer in the documentation
12ccec91a1Sjoerg * and/or other materials provided with the distribution.
13ccec91a1Sjoerg *
14ccec91a1Sjoerg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
15ccec91a1Sjoerg * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16ccec91a1Sjoerg * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17ccec91a1Sjoerg * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
18ccec91a1Sjoerg * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19ccec91a1Sjoerg * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20ccec91a1Sjoerg * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21ccec91a1Sjoerg * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22ccec91a1Sjoerg * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23ccec91a1Sjoerg * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24ccec91a1Sjoerg * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25ccec91a1Sjoerg */
26ccec91a1Sjoerg /**
27ccec91a1Sjoerg * dwarf_eh.h - Defines some helper functions for parsing DWARF exception
28ccec91a1Sjoerg * handling tables.
29ccec91a1Sjoerg *
30ccec91a1Sjoerg * This file contains various helper functions that are independent of the
31ccec91a1Sjoerg * language-specific code. It can be used in any personality function for the
32ccec91a1Sjoerg * Itanium ABI.
33ccec91a1Sjoerg */
34ccec91a1Sjoerg #include <assert.h>
35ccec91a1Sjoerg
36ccec91a1Sjoerg // TODO: Factor out Itanium / ARM differences. We probably want an itanium.h
37ccec91a1Sjoerg // and arm.h that can be included by this file depending on the target ABI.
38ccec91a1Sjoerg
39ccec91a1Sjoerg // _GNU_SOURCE must be defined for unwind.h to expose some of the functions
40ccec91a1Sjoerg // that we want. If it isn't, then we define it and undefine it to make sure
41ccec91a1Sjoerg // that it doesn't impact the rest of the program.
42ccec91a1Sjoerg #ifndef _GNU_SOURCE
43ccec91a1Sjoerg # define _GNU_SOURCE 1
44ccec91a1Sjoerg # include "unwind.h"
45ccec91a1Sjoerg # undef _GNU_SOURCE
46ccec91a1Sjoerg #else
47ccec91a1Sjoerg # include "unwind.h"
48ccec91a1Sjoerg #endif
49ccec91a1Sjoerg
50ccec91a1Sjoerg #include <stdint.h>
51ccec91a1Sjoerg
52ccec91a1Sjoerg /// Type used for pointers into DWARF data
53ccec91a1Sjoerg typedef unsigned char *dw_eh_ptr_t;
54ccec91a1Sjoerg
55ccec91a1Sjoerg // Flag indicating a signed quantity
56ccec91a1Sjoerg #define DW_EH_PE_signed 0x08
57ccec91a1Sjoerg /// DWARF data encoding types.
58ccec91a1Sjoerg enum dwarf_data_encoding
59ccec91a1Sjoerg {
605067d178Sjoerg /// Absolute pointer value
615067d178Sjoerg DW_EH_PE_absptr = 0x00,
62ccec91a1Sjoerg /// Unsigned, little-endian, base 128-encoded (variable length).
63ccec91a1Sjoerg DW_EH_PE_uleb128 = 0x01,
64ccec91a1Sjoerg /// Unsigned 16-bit integer.
65ccec91a1Sjoerg DW_EH_PE_udata2 = 0x02,
66ccec91a1Sjoerg /// Unsigned 32-bit integer.
67ccec91a1Sjoerg DW_EH_PE_udata4 = 0x03,
68ccec91a1Sjoerg /// Unsigned 64-bit integer.
69ccec91a1Sjoerg DW_EH_PE_udata8 = 0x04,
70ccec91a1Sjoerg /// Signed, little-endian, base 128-encoded (variable length)
71ccec91a1Sjoerg DW_EH_PE_sleb128 = DW_EH_PE_uleb128 | DW_EH_PE_signed,
72ccec91a1Sjoerg /// Signed 16-bit integer.
73ccec91a1Sjoerg DW_EH_PE_sdata2 = DW_EH_PE_udata2 | DW_EH_PE_signed,
74ccec91a1Sjoerg /// Signed 32-bit integer.
75ccec91a1Sjoerg DW_EH_PE_sdata4 = DW_EH_PE_udata4 | DW_EH_PE_signed,
76ccec91a1Sjoerg /// Signed 32-bit integer.
77ccec91a1Sjoerg DW_EH_PE_sdata8 = DW_EH_PE_udata8 | DW_EH_PE_signed
78ccec91a1Sjoerg };
79ccec91a1Sjoerg
80ccec91a1Sjoerg /**
81ccec91a1Sjoerg * Returns the encoding for a DWARF EH table entry. The encoding is stored in
82ccec91a1Sjoerg * the low four of an octet. The high four bits store the addressing mode.
83ccec91a1Sjoerg */
get_encoding(unsigned char x)84ccec91a1Sjoerg static inline enum dwarf_data_encoding get_encoding(unsigned char x)
85ccec91a1Sjoerg {
86d0b6b5d5Sjoerg return static_cast<enum dwarf_data_encoding>(x & 0xf);
87ccec91a1Sjoerg }
88ccec91a1Sjoerg
89ccec91a1Sjoerg /**
90ccec91a1Sjoerg * DWARF addressing mode constants. When reading a pointer value from a DWARF
91ccec91a1Sjoerg * exception table, you must know how it is stored and what the addressing mode
92ccec91a1Sjoerg * is. The low four bits tell you the encoding, allowing you to decode a
93ccec91a1Sjoerg * number. The high four bits tell you the addressing mode, allowing you to
94ccec91a1Sjoerg * turn that number into an address in memory.
95ccec91a1Sjoerg */
96ccec91a1Sjoerg enum dwarf_data_relative
97ccec91a1Sjoerg {
98ccec91a1Sjoerg /// Value is omitted
99ccec91a1Sjoerg DW_EH_PE_omit = 0xff,
100ccec91a1Sjoerg /// Value relative to program counter
101ccec91a1Sjoerg DW_EH_PE_pcrel = 0x10,
102ccec91a1Sjoerg /// Value relative to the text segment
103ccec91a1Sjoerg DW_EH_PE_textrel = 0x20,
104ccec91a1Sjoerg /// Value relative to the data segment
105ccec91a1Sjoerg DW_EH_PE_datarel = 0x30,
106ccec91a1Sjoerg /// Value relative to the start of the function
107ccec91a1Sjoerg DW_EH_PE_funcrel = 0x40,
108ccec91a1Sjoerg /// Aligned pointer (Not supported yet - are they actually used?)
109ccec91a1Sjoerg DW_EH_PE_aligned = 0x50,
110ccec91a1Sjoerg /// Pointer points to address of real value
111ccec91a1Sjoerg DW_EH_PE_indirect = 0x80
112ccec91a1Sjoerg };
113ccec91a1Sjoerg /**
114ccec91a1Sjoerg * Returns the addressing mode component of this encoding.
115ccec91a1Sjoerg */
get_base(unsigned char x)116ccec91a1Sjoerg static inline enum dwarf_data_relative get_base(unsigned char x)
117ccec91a1Sjoerg {
118d0b6b5d5Sjoerg return static_cast<enum dwarf_data_relative>(x & 0x70);
119ccec91a1Sjoerg }
120ccec91a1Sjoerg /**
121ccec91a1Sjoerg * Returns whether an encoding represents an indirect address.
122ccec91a1Sjoerg */
is_indirect(unsigned char x)123ccec91a1Sjoerg static int is_indirect(unsigned char x)
124ccec91a1Sjoerg {
125ccec91a1Sjoerg return ((x & DW_EH_PE_indirect) == DW_EH_PE_indirect);
126ccec91a1Sjoerg }
127ccec91a1Sjoerg
128ccec91a1Sjoerg /**
129ccec91a1Sjoerg * Returns the size of a fixed-size encoding. This function will abort if
130ccec91a1Sjoerg * called with a value that is not a fixed-size encoding.
131ccec91a1Sjoerg */
dwarf_size_of_fixed_size_field(unsigned char type)132ccec91a1Sjoerg static inline int dwarf_size_of_fixed_size_field(unsigned char type)
133ccec91a1Sjoerg {
134ccec91a1Sjoerg switch (get_encoding(type))
135ccec91a1Sjoerg {
136ccec91a1Sjoerg default: abort();
137ccec91a1Sjoerg case DW_EH_PE_sdata2:
138ccec91a1Sjoerg case DW_EH_PE_udata2: return 2;
139ccec91a1Sjoerg case DW_EH_PE_sdata4:
140ccec91a1Sjoerg case DW_EH_PE_udata4: return 4;
141ccec91a1Sjoerg case DW_EH_PE_sdata8:
142ccec91a1Sjoerg case DW_EH_PE_udata8: return 8;
143ccec91a1Sjoerg case DW_EH_PE_absptr: return sizeof(void*);
144ccec91a1Sjoerg }
145ccec91a1Sjoerg }
146ccec91a1Sjoerg
147ccec91a1Sjoerg /**
148ccec91a1Sjoerg * Read an unsigned, little-endian, base-128, DWARF value. Updates *data to
149ccec91a1Sjoerg * point to the end of the value. Stores the number of bits read in the value
150ccec91a1Sjoerg * pointed to by b, allowing you to determine the value of the highest bit, and
151ccec91a1Sjoerg * therefore the sign of a signed value.
152ccec91a1Sjoerg *
153ccec91a1Sjoerg * This function is not intended to be called directly. Use read_sleb128() or
154ccec91a1Sjoerg * read_uleb128() for reading signed and unsigned versions, respectively.
155ccec91a1Sjoerg */
read_leb128(dw_eh_ptr_t * data,int * b)156ccec91a1Sjoerg static uint64_t read_leb128(dw_eh_ptr_t *data, int *b)
157ccec91a1Sjoerg {
158ccec91a1Sjoerg uint64_t uleb = 0;
159ccec91a1Sjoerg unsigned int bit = 0;
160ccec91a1Sjoerg unsigned char digit = 0;
161ccec91a1Sjoerg // We have to read at least one octet, and keep reading until we get to one
162ccec91a1Sjoerg // with the high bit unset
163ccec91a1Sjoerg do
164ccec91a1Sjoerg {
165ccec91a1Sjoerg // This check is a bit too strict - we should also check the highest
166ccec91a1Sjoerg // bit of the digit.
167ccec91a1Sjoerg assert(bit < sizeof(uint64_t) * 8);
168ccec91a1Sjoerg // Get the base 128 digit
169ccec91a1Sjoerg digit = (**data) & 0x7f;
170ccec91a1Sjoerg // Add it to the current value
171ccec91a1Sjoerg uleb += digit << bit;
172ccec91a1Sjoerg // Increase the shift value
173ccec91a1Sjoerg bit += 7;
174ccec91a1Sjoerg // Proceed to the next octet
175ccec91a1Sjoerg (*data)++;
176ccec91a1Sjoerg // Terminate when we reach a value that does not have the high bit set
177ccec91a1Sjoerg // (i.e. which was not modified when we mask it with 0x7f)
178ccec91a1Sjoerg } while ((*(*data - 1)) != digit);
179ccec91a1Sjoerg *b = bit;
180ccec91a1Sjoerg
181ccec91a1Sjoerg return uleb;
182ccec91a1Sjoerg }
183ccec91a1Sjoerg
184ccec91a1Sjoerg /**
185ccec91a1Sjoerg * Reads an unsigned little-endian base-128 value starting at the address
186ccec91a1Sjoerg * pointed to by *data. Updates *data to point to the next byte after the end
187ccec91a1Sjoerg * of the variable-length value.
188ccec91a1Sjoerg */
read_uleb128(dw_eh_ptr_t * data)189ccec91a1Sjoerg static int64_t read_uleb128(dw_eh_ptr_t *data)
190ccec91a1Sjoerg {
191ccec91a1Sjoerg int b;
192ccec91a1Sjoerg return read_leb128(data, &b);
193ccec91a1Sjoerg }
194ccec91a1Sjoerg
195ccec91a1Sjoerg /**
196ccec91a1Sjoerg * Reads a signed little-endian base-128 value starting at the address pointed
197ccec91a1Sjoerg * to by *data. Updates *data to point to the next byte after the end of the
198ccec91a1Sjoerg * variable-length value.
199ccec91a1Sjoerg */
read_sleb128(dw_eh_ptr_t * data)200ccec91a1Sjoerg static int64_t read_sleb128(dw_eh_ptr_t *data)
201ccec91a1Sjoerg {
202ccec91a1Sjoerg int bits;
203ccec91a1Sjoerg // Read as if it's signed
204ccec91a1Sjoerg uint64_t uleb = read_leb128(data, &bits);
205ccec91a1Sjoerg // If the most significant bit read is 1, then we need to sign extend it
206ccec91a1Sjoerg if ((uleb >> (bits-1)) == 1)
207ccec91a1Sjoerg {
208ccec91a1Sjoerg // Sign extend by setting all bits in front of it to 1
209d0b6b5d5Sjoerg uleb |= static_cast<int64_t>(-1) << bits;
210ccec91a1Sjoerg }
211d0b6b5d5Sjoerg return static_cast<int64_t>(uleb);
212ccec91a1Sjoerg }
213ccec91a1Sjoerg /**
214ccec91a1Sjoerg * Reads a value using the specified encoding from the address pointed to by
215ccec91a1Sjoerg * *data. Updates the value of *data to point to the next byte after the end
216ccec91a1Sjoerg * of the data.
217ccec91a1Sjoerg */
read_value(char encoding,dw_eh_ptr_t * data)218ccec91a1Sjoerg static uint64_t read_value(char encoding, dw_eh_ptr_t *data)
219ccec91a1Sjoerg {
220ccec91a1Sjoerg enum dwarf_data_encoding type = get_encoding(encoding);
221ccec91a1Sjoerg switch (type)
222ccec91a1Sjoerg {
223ccec91a1Sjoerg // Read fixed-length types
224ccec91a1Sjoerg #define READ(dwarf, type) \
225ccec91a1Sjoerg case dwarf:\
226*fec583f4Spooka {\
227*fec583f4Spooka type t;\
228*fec583f4Spooka memcpy(&t, *data, sizeof t);\
229*fec583f4Spooka *data += sizeof t;\
230*fec583f4Spooka return static_cast<uint64_t>(t);\
231*fec583f4Spooka }
232ccec91a1Sjoerg READ(DW_EH_PE_udata2, uint16_t)
233ccec91a1Sjoerg READ(DW_EH_PE_udata4, uint32_t)
234ccec91a1Sjoerg READ(DW_EH_PE_udata8, uint64_t)
235ccec91a1Sjoerg READ(DW_EH_PE_sdata2, int16_t)
236ccec91a1Sjoerg READ(DW_EH_PE_sdata4, int32_t)
237ccec91a1Sjoerg READ(DW_EH_PE_sdata8, int64_t)
238ccec91a1Sjoerg READ(DW_EH_PE_absptr, intptr_t)
239ccec91a1Sjoerg #undef READ
240ccec91a1Sjoerg // Read variable-length types
241ccec91a1Sjoerg case DW_EH_PE_sleb128:
242*fec583f4Spooka return read_sleb128(data);
243ccec91a1Sjoerg case DW_EH_PE_uleb128:
244*fec583f4Spooka return read_uleb128(data);
245ccec91a1Sjoerg default: abort();
246ccec91a1Sjoerg }
247ccec91a1Sjoerg }
248ccec91a1Sjoerg
249ccec91a1Sjoerg /**
250ccec91a1Sjoerg * Resolves an indirect value. This expects an unwind context, an encoding, a
251ccec91a1Sjoerg * decoded value, and the start of the region as arguments. The returned value
252ccec91a1Sjoerg * is a pointer to the address identified by the encoded value.
253ccec91a1Sjoerg *
254ccec91a1Sjoerg * If the encoding does not specify an indirect value, then this returns v.
255ccec91a1Sjoerg */
resolve_indirect_value(_Unwind_Context * c,unsigned char encoding,int64_t v,dw_eh_ptr_t start)256ccec91a1Sjoerg static uint64_t resolve_indirect_value(_Unwind_Context *c,
257ccec91a1Sjoerg unsigned char encoding,
258ccec91a1Sjoerg int64_t v,
259ccec91a1Sjoerg dw_eh_ptr_t start)
260ccec91a1Sjoerg {
261ccec91a1Sjoerg switch (get_base(encoding))
262ccec91a1Sjoerg {
263ccec91a1Sjoerg case DW_EH_PE_pcrel:
264d0b6b5d5Sjoerg v += reinterpret_cast<uint64_t>(start);
265ccec91a1Sjoerg break;
266ccec91a1Sjoerg case DW_EH_PE_textrel:
267d0b6b5d5Sjoerg v += static_cast<uint64_t>(static_cast<uintptr_t>(_Unwind_GetTextRelBase(c)));
268ccec91a1Sjoerg break;
269ccec91a1Sjoerg case DW_EH_PE_datarel:
270d0b6b5d5Sjoerg v += static_cast<uint64_t>(static_cast<uintptr_t>(_Unwind_GetDataRelBase(c)));
271ccec91a1Sjoerg break;
272ccec91a1Sjoerg case DW_EH_PE_funcrel:
273d0b6b5d5Sjoerg v += static_cast<uint64_t>(static_cast<uintptr_t>(_Unwind_GetRegionStart(c)));
274ccec91a1Sjoerg default:
275ccec91a1Sjoerg break;
276ccec91a1Sjoerg }
277ccec91a1Sjoerg // If this is an indirect value, then it is really the address of the real
278ccec91a1Sjoerg // value
279ccec91a1Sjoerg // TODO: Check whether this should really always be a pointer - it seems to
280ccec91a1Sjoerg // be a GCC extensions, so not properly documented...
281ccec91a1Sjoerg if (is_indirect(encoding))
282ccec91a1Sjoerg {
283d0b6b5d5Sjoerg v = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(*reinterpret_cast<void**>(v)));
284ccec91a1Sjoerg }
285ccec91a1Sjoerg return v;
286ccec91a1Sjoerg }
287ccec91a1Sjoerg
288ccec91a1Sjoerg
289ccec91a1Sjoerg /**
290ccec91a1Sjoerg * Reads an encoding and a value, updating *data to point to the next byte.
291ccec91a1Sjoerg */
read_value_with_encoding(_Unwind_Context * context,dw_eh_ptr_t * data,uint64_t * out)292ccec91a1Sjoerg static inline void read_value_with_encoding(_Unwind_Context *context,
293ccec91a1Sjoerg dw_eh_ptr_t *data,
294ccec91a1Sjoerg uint64_t *out)
295ccec91a1Sjoerg {
296ccec91a1Sjoerg dw_eh_ptr_t start = *data;
297ccec91a1Sjoerg unsigned char encoding = *((*data)++);
298ccec91a1Sjoerg // If this value is omitted, skip it and don't touch the output value
299ccec91a1Sjoerg if (encoding == DW_EH_PE_omit) { return; }
300ccec91a1Sjoerg
301ccec91a1Sjoerg *out = read_value(encoding, data);
302ccec91a1Sjoerg *out = resolve_indirect_value(context, encoding, *out, start);
303ccec91a1Sjoerg }
304ccec91a1Sjoerg
305ccec91a1Sjoerg /**
306ccec91a1Sjoerg * Structure storing a decoded language-specific data area. Use parse_lsda()
307ccec91a1Sjoerg * to generate an instance of this structure from the address returned by the
308ccec91a1Sjoerg * generic unwind library.
309ccec91a1Sjoerg *
310ccec91a1Sjoerg * You should not need to inspect the fields of this structure directly if you
311ccec91a1Sjoerg * are just using this header. The structure stores the locations of the
312ccec91a1Sjoerg * various tables used for unwinding exceptions and is used by the functions
313ccec91a1Sjoerg * for reading values from these tables.
314ccec91a1Sjoerg */
315ccec91a1Sjoerg struct dwarf_eh_lsda
316ccec91a1Sjoerg {
317ccec91a1Sjoerg /// The start of the region. This is a cache of the value returned by
318ccec91a1Sjoerg /// _Unwind_GetRegionStart().
319ccec91a1Sjoerg dw_eh_ptr_t region_start;
320ccec91a1Sjoerg /// The start of the landing pads table.
321ccec91a1Sjoerg dw_eh_ptr_t landing_pads;
322ccec91a1Sjoerg /// The start of the type table.
323ccec91a1Sjoerg dw_eh_ptr_t type_table;
324ccec91a1Sjoerg /// The encoding used for entries in the type tables.
325ccec91a1Sjoerg unsigned char type_table_encoding;
326ccec91a1Sjoerg /// The location of the call-site table.
327ccec91a1Sjoerg dw_eh_ptr_t call_site_table;
328ccec91a1Sjoerg /// The location of the action table.
329ccec91a1Sjoerg dw_eh_ptr_t action_table;
330ccec91a1Sjoerg /// The encoding used for entries in the call-site table.
331ccec91a1Sjoerg unsigned char callsite_encoding;
332ccec91a1Sjoerg };
333ccec91a1Sjoerg
334ccec91a1Sjoerg /**
335ccec91a1Sjoerg * Parse the header on the language-specific data area and return a structure
336ccec91a1Sjoerg * containing the addresses and encodings of the various tables.
337ccec91a1Sjoerg */
parse_lsda(_Unwind_Context * context,unsigned char * data)338ccec91a1Sjoerg static inline struct dwarf_eh_lsda parse_lsda(_Unwind_Context *context,
339ccec91a1Sjoerg unsigned char *data)
340ccec91a1Sjoerg {
341ccec91a1Sjoerg struct dwarf_eh_lsda lsda;
342ccec91a1Sjoerg
343d0b6b5d5Sjoerg lsda.region_start = reinterpret_cast<dw_eh_ptr_t>(_Unwind_GetRegionStart(context));
344ccec91a1Sjoerg
345ccec91a1Sjoerg // If the landing pads are relative to anything other than the start of
346ccec91a1Sjoerg // this region, find out where. This is @LPStart in the spec, although the
347ccec91a1Sjoerg // encoding that GCC uses does not quite match the spec.
348d0b6b5d5Sjoerg uint64_t v = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(lsda.region_start));
349ccec91a1Sjoerg read_value_with_encoding(context, &data, &v);
350d0b6b5d5Sjoerg lsda.landing_pads = reinterpret_cast<dw_eh_ptr_t>(static_cast<uintptr_t>(v));
351ccec91a1Sjoerg
352ccec91a1Sjoerg // If there is a type table, find out where it is. This is @TTBase in the
353ccec91a1Sjoerg // spec. Note: we find whether there is a type table pointer by checking
354ccec91a1Sjoerg // whether the leading byte is DW_EH_PE_omit (0xff), which is not what the
355ccec91a1Sjoerg // spec says, but does seem to be how G++ indicates this.
356ccec91a1Sjoerg lsda.type_table = 0;
357ccec91a1Sjoerg lsda.type_table_encoding = *data++;
358ccec91a1Sjoerg if (lsda.type_table_encoding != DW_EH_PE_omit)
359ccec91a1Sjoerg {
360ccec91a1Sjoerg v = read_uleb128(&data);
361ccec91a1Sjoerg dw_eh_ptr_t type_table = data;
362ccec91a1Sjoerg type_table += v;
363ccec91a1Sjoerg lsda.type_table = type_table;
364ccec91a1Sjoerg //lsda.type_table = (uintptr_t*)(data + v);
365ccec91a1Sjoerg }
3668b0d15c4Sjoerg #if defined(__arm__) && !defined(__ARM_DWARF_EH__)
367ccec91a1Sjoerg lsda.type_table_encoding = (DW_EH_PE_pcrel | DW_EH_PE_indirect);
368ccec91a1Sjoerg #endif
369ccec91a1Sjoerg
370d0b6b5d5Sjoerg lsda.callsite_encoding = static_cast<enum dwarf_data_encoding>(*(data++));
371ccec91a1Sjoerg
372ccec91a1Sjoerg // Action table is immediately after the call site table
373ccec91a1Sjoerg lsda.action_table = data;
374d0b6b5d5Sjoerg uintptr_t callsite_size = static_cast<uintptr_t>(read_uleb128(&data));
375ccec91a1Sjoerg lsda.action_table = data + callsite_size;
376ccec91a1Sjoerg // Call site table is immediately after the header
377d0b6b5d5Sjoerg lsda.call_site_table = static_cast<dw_eh_ptr_t>(data);
378ccec91a1Sjoerg
379ccec91a1Sjoerg
380ccec91a1Sjoerg return lsda;
381ccec91a1Sjoerg }
382ccec91a1Sjoerg
383ccec91a1Sjoerg /**
384ccec91a1Sjoerg * Structure representing an action to be performed while unwinding. This
385ccec91a1Sjoerg * contains the address that should be unwound to and the action record that
386ccec91a1Sjoerg * provoked this action.
387ccec91a1Sjoerg */
388ccec91a1Sjoerg struct dwarf_eh_action
389ccec91a1Sjoerg {
390ccec91a1Sjoerg /**
391ccec91a1Sjoerg * The address that this action directs should be the new program counter
392ccec91a1Sjoerg * value after unwinding.
393ccec91a1Sjoerg */
394ccec91a1Sjoerg dw_eh_ptr_t landing_pad;
395ccec91a1Sjoerg /// The address of the action record.
396ccec91a1Sjoerg dw_eh_ptr_t action_record;
397ccec91a1Sjoerg };
398ccec91a1Sjoerg
399ccec91a1Sjoerg /**
400ccec91a1Sjoerg * Look up the landing pad that corresponds to the current invoke.
401ccec91a1Sjoerg * Returns true if record exists. The context is provided by the generic
402ccec91a1Sjoerg * unwind library and the lsda should be the result of a call to parse_lsda().
403ccec91a1Sjoerg *
404ccec91a1Sjoerg * The action record is returned via the result parameter.
405ccec91a1Sjoerg */
dwarf_eh_find_callsite(struct _Unwind_Context * context,struct dwarf_eh_lsda * lsda,struct dwarf_eh_action * result)406ccec91a1Sjoerg static bool dwarf_eh_find_callsite(struct _Unwind_Context *context,
407ccec91a1Sjoerg struct dwarf_eh_lsda *lsda,
408ccec91a1Sjoerg struct dwarf_eh_action *result)
409ccec91a1Sjoerg {
410ccec91a1Sjoerg result->action_record = 0;
411ccec91a1Sjoerg result->landing_pad = 0;
412ccec91a1Sjoerg // The current instruction pointer offset within the region
413ccec91a1Sjoerg uint64_t ip = _Unwind_GetIP(context) - _Unwind_GetRegionStart(context);
414d0b6b5d5Sjoerg unsigned char *callsite_table = static_cast<unsigned char*>(lsda->call_site_table);
415ccec91a1Sjoerg
416ccec91a1Sjoerg while (callsite_table <= lsda->action_table)
417ccec91a1Sjoerg {
418ccec91a1Sjoerg // Once again, the layout deviates from the spec.
419ccec91a1Sjoerg uint64_t call_site_start, call_site_size, landing_pad, action;
420ccec91a1Sjoerg call_site_start = read_value(lsda->callsite_encoding, &callsite_table);
421ccec91a1Sjoerg call_site_size = read_value(lsda->callsite_encoding, &callsite_table);
422ccec91a1Sjoerg
423ccec91a1Sjoerg // Call site entries are sorted, so if we find a call site that's after
424ccec91a1Sjoerg // the current instruction pointer then there is no action associated
425ccec91a1Sjoerg // with this call and we should unwind straight through this frame
426ccec91a1Sjoerg // without doing anything.
427ccec91a1Sjoerg if (call_site_start > ip) { break; }
428ccec91a1Sjoerg
429ccec91a1Sjoerg // Read the address of the landing pad and the action from the call
430ccec91a1Sjoerg // site table.
431ccec91a1Sjoerg landing_pad = read_value(lsda->callsite_encoding, &callsite_table);
432ccec91a1Sjoerg action = read_uleb128(&callsite_table);
433ccec91a1Sjoerg
434ccec91a1Sjoerg // We should not include the call_site_start (beginning of the region)
435ccec91a1Sjoerg // address in the ip range. For each call site:
436ccec91a1Sjoerg //
437ccec91a1Sjoerg // address1: call proc
438ccec91a1Sjoerg // address2: next instruction
439ccec91a1Sjoerg //
440ccec91a1Sjoerg // The call stack contains address2 and not address1, address1 can be
441ccec91a1Sjoerg // at the end of another EH region.
442ccec91a1Sjoerg if (call_site_start < ip && ip <= call_site_start + call_site_size)
443ccec91a1Sjoerg {
444ccec91a1Sjoerg if (action)
445ccec91a1Sjoerg {
446ccec91a1Sjoerg // Action records are 1-biased so both no-record and zeroth
447ccec91a1Sjoerg // record can be stored.
448ccec91a1Sjoerg result->action_record = lsda->action_table + action - 1;
449ccec91a1Sjoerg }
450ccec91a1Sjoerg // No landing pad means keep unwinding.
451ccec91a1Sjoerg if (landing_pad)
452ccec91a1Sjoerg {
453ccec91a1Sjoerg // Landing pad is the offset from the value in the header
454ccec91a1Sjoerg result->landing_pad = lsda->landing_pads + landing_pad;
455ccec91a1Sjoerg }
456ccec91a1Sjoerg return true;
457ccec91a1Sjoerg }
458ccec91a1Sjoerg }
459ccec91a1Sjoerg return false;
460ccec91a1Sjoerg }
461ccec91a1Sjoerg
462ccec91a1Sjoerg /// Defines an exception class from 8 bytes (endian independent)
463ccec91a1Sjoerg #define EXCEPTION_CLASS(a,b,c,d,e,f,g,h) \
464d0b6b5d5Sjoerg ((static_cast<uint64_t>(a) << 56) +\
465d0b6b5d5Sjoerg (static_cast<uint64_t>(b) << 48) +\
466d0b6b5d5Sjoerg (static_cast<uint64_t>(c) << 40) +\
467d0b6b5d5Sjoerg (static_cast<uint64_t>(d) << 32) +\
468d0b6b5d5Sjoerg (static_cast<uint64_t>(e) << 24) +\
469d0b6b5d5Sjoerg (static_cast<uint64_t>(f) << 16) +\
470d0b6b5d5Sjoerg (static_cast<uint64_t>(g) << 8) +\
471d0b6b5d5Sjoerg (static_cast<uint64_t>(h)))
472ccec91a1Sjoerg
473ccec91a1Sjoerg #define GENERIC_EXCEPTION_CLASS(e,f,g,h) \
474d0b6b5d5Sjoerg (static_cast<uint32_t>(e) << 24) +\
475d0b6b5d5Sjoerg (static_cast<uint32_t>(f) << 16) +\
476d0b6b5d5Sjoerg (static_cast<uint32_t>(g) << 8) +\
477d0b6b5d5Sjoerg (static_cast<uint32_t>(h))
478